Mission accomplished. Thank you to all who answered, not only for coding suggestions, but also for alternative ways of considering the problem. Ultimately, I went with a form of ballardw's response - largely because it made the most immediate sense to me. %macro productloop ; %let yearinteger = 2000 ; %do vsn = 1 %to 61 ; data _null_; %if %sysfunc(mod(&vsn,4))= 1 %then %do ; call symput("startdt", "'01-JAN-"||strip(&yearinteger.)||"'") ; call symput("enddt", "'31-MAR-"||strip(&yearinteger.)||"'") ; %let quarter = "Q1" ; %let twodigityear = substrn(&yearinteger.,3,2) ; call symput("mergeset", "<filepath>"||&twodigityear.||&quarter.) ; call symput("g1filename", "<filepath>"||&twodigityear.||&quarter.||"G1") ; call symput("g2filename", "<filepath>"||&twodigityear.||&quarter.||"G2") ; call symput("g1output", "'<filepath>"||&twodigityear.||&quarter.||"G1.csv'") ; call symput("g2output", "'<filepath>"||&twodigityear.||&quarter.||"G2.csv'") ; %datagen; %end ; %else %if %sysfunc(mod(&vsn,4))= 2 %then %do ; call symput("startdt", "'01-APR-"||strip(&yearinteger.)||"'") ; call symput("enddt", "'30-JUN-"||strip(&yearinteger.)||"'") ; %let quarter = "Q2" ; %let twodigityear = substrn(&yearinteger.,3,2) ; call symput("mergeset", "<filepath>"||&twodigityear.||&quarter.) ; call symput("g1filename", "<filepath>"||&twodigityear.||&quarter.||"G1") ; call symput("g2filename", "<filepath>"||&twodigityear.||&quarter.||"G2") ; call symput("g1output", "'<filepath>"||&twodigityear.||&quarter.||"G1.csv'") ; call symput("g2output", "'<filepath>"||&twodigityear.||&quarter.||"G2.csv'") ; %datagen; %end ; %else %if %sysfunc(mod(&vsn,4))= 3 %then %do ; call symput("startdt", "'01-JUL-"||strip(&yearinteger.)||"'") ; call symput("enddt", "'30-SEP-"||strip(&yearinteger.)||"'") ; %let quarter = "Q3" ; %let twodigityear = substrn(&yearinteger.,3,2) ; call symput("mergeset", "<filepath>"||&twodigityear.||&quarter.) ; call symput("g1filename", "<filepath>"||&twodigityear.||&quarter.||"G1") ; call symput("g2filename", "<filepath>"||&twodigityear.||&quarter.||"G2") ; call symput("g1output", "'<filepath>"||&twodigityear.||&quarter.||"G1.csv'") ; call symput("g2output", "'<filepath>"||&twodigityear.||&quarter.||"G2.csv'") ; %datagen; %end ; %else %do ; call symput("startdt", "'01-OCT-"||strip(&yearinteger.)||"'") ; call symput("enddt", "'31-DEC-"||strip(&yearinteger.)||"'") ; %let quarter = "Q4" ; %let twodigityear = substrn(&yearinteger.,3,2) ; call symput("mergeset", "<filepath>"||&twodigityear.||&quarter.) ; call symput("g1filename", "<filepath>"||&twodigityear.||&quarter.||"G1") ; call symput("g2filename", "<filepath>"||&twodigityear.||&quarter.||"G2") ; call symput("g1output", "'<filepath>"||&twodigityear.||&quarter.||"G1.csv'") ; call symput("g2output", "'<filepath>"||&twodigityear.||&quarter.||"G2.csv'") ; %datagen; data _null_ ; %let yearinteger = sum(&yearinteger., 1) ; %end ; %end ; run; %mend productloop ; This is the outer loop, within which I ran the "datagen" macro, which merged tables with proc sql and performed the various calculations I needed to do while using the myriad macro variables defined in said outer loop. It is perhaps not the most elegant code, but what it lacks in beauty it makes up for in functionality. A few notable hang-ups: I did not know that the "call symput" function required a preceding "data _null_" declaration, creating a situation in which the first data set would be created without a problem, but subsequent iterations would error out without any explanation as to why within the log. Fixed by placing a "data _null_" statement at the top of the loop. The difference between "%let" and "call symput" remains somewhat elusive to me, though I had to switch between the two quite a bit before the resulting code behaved as desired. Similarly, while the difference between "if" and "%if" is clear enough (I think), it's not immediately obvious to me why the macro versions of the other commands/functions (%to, %do, %end, etc.) were necessary, aside from the fact that the code wouldn't run otherwise. Anyway, just wanted to give a final update and a hearty "thank you" for the assistance. I've got quite a bit to learn yet, but this has taught me a substantial amount. Cheers.
... View more