Hello
I want to create series of macro variables in form YYMM from 2 months before &start until &end
In this example start=1901 end=1903 so I want to create series of macro varaibles:
m0=1811
m1=1812
m2=1901
m3=1902
m4=1903
However, in the following code I get all macro parameter values equal 1903.
What is the mistake in the logic please?
%let start=1901;
%let end=1903;
%let date_start=%sysfunc(inputn(&start.,yymmn4.));
%let date_end=%sysfunc(inputn(&end.,yymmn4.));
%put &date_start. ;/*21550*/
%put &date_end. ; /*21609*/
data _null_;
n1=intck('month',&date_start.,&date_end.);
n2=n1+2;
call symput("n1",trim(left(n1)));
call symput("n2",trim(left(n2)));
run;
%put &n1;
%put &n2;
%macro months;
%do i=-2 %to &n1.;
%do j=0 %to &n2.;
m&j.=put(intnx('month',&date_start.,&i.),yymmn4.);
call symput("m&j",trim(left(m&j.)));
%end;
%end;
%mend;
data aaa;
%months;
run;
%put &&m&n2;
%put &m0;
You are massively overcomplicating things by abusing the poor macro processor.
Such things are easily done in one simple data step:
%let start=1901;
%let end=1903;
data control;
start = intnx('month',input("&start",yymmn4.),-2,'b');
end = input("&end.",yymmn4.);
length month $4;
m = 0;
do until (start > end);
month = put(start,yymmn4.);
call symputx(cats('M',m),month);
output;
m + 1;
start = intnx('month',start,1,'b');
end;
keep month;
run;
%put &m0 &m1 &m2 &m3 &m4;
proc print data=control noobs;
run;
Log excerpt:
42 %put &m0 &m1 &m2 &m3 &m4; 1811 1812 1901 1902 1903
Result of print:
month 1811 1812 1901 1902 1903
I created the dataset because data has to be kept in datasets, not unwieldy macro variable lists. The control dataset can easily be used to create dynamic code with call execute.
You are massively overcomplicating things by abusing the poor macro processor.
Such things are easily done in one simple data step:
%let start=1901;
%let end=1903;
data control;
start = intnx('month',input("&start",yymmn4.),-2,'b');
end = input("&end.",yymmn4.);
length month $4;
m = 0;
do until (start > end);
month = put(start,yymmn4.);
call symputx(cats('M',m),month);
output;
m + 1;
start = intnx('month',start,1,'b');
end;
keep month;
run;
%put &m0 &m1 &m2 &m3 &m4;
proc print data=control noobs;
run;
Log excerpt:
42 %put &m0 &m1 &m2 &m3 &m4; 1811 1812 1901 1902 1903
Result of print:
month 1811 1812 1901 1902 1903
I created the dataset because data has to be kept in datasets, not unwieldy macro variable lists. The control dataset can easily be used to create dynamic code with call execute.
Perfect solution.
Thank you.
I am still interested to know what is the error in my code
@Ronein wrote:
Perfect solution.
Thank you.
I am still interested to know what is the error in my code
Your use of two nested %do loops. When the outer loop reaches 1903, the inner loop overwrites all variables.
Even that logic does not need any macro code at all:
data aaa;
array m {%eval(&n2.+1)} m0-m&n2.;
format m0-m&n2. yymmn4.;
do i = 0 to &n2.;
m{i+1} = intnx('month',&date_start.,i-2);
end;
drop i;
run;
Maxim 11
Maxim 11
Maxim 11
I believe nearly 2 years ago when you started posting and were using "dates" in this form YYMM I mentioned that actually using a date value and using an appropriate format to display the date would be easier in the long run.
I am not sure but I suspect this is at least the 20th post you have regarding manipulating dates in this non-date form.
Note that the first thing you have to do each an every time is build a date value to increment or manipulate things.
I have not seen anything where use of YYMM appearing numeric values has made any of your tasks simpler or easier to follow.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.