Hi,
Please help me on this nested do loop issue:-
Below is the code:-
%macro update();
%do i=1 %to 12;
%do j=9 %to 13;
%if %length(&i)=1 %then %let yr=200&i;
%else yr=20&i;
%if %length(&j)=1 %then %let mon=0&j.;
%else mon=&j.;
%let vname=&yr&mon;
%end;
%end;
%mend;
%update;
Thanks in Advance.
You have already gotten a number of good suggestions here. Let me draw from them to summarize what you could do:
%macro update;
%local i j;
%do i=1 %to 12;
%do j=9 %to 13;
%let vname=20%sysfunc(putn(&j,z2))%sysfunc(putn(&i,z2));
%end;
%end;
%mend update;
Of course there must be more to your objective than this. The way the code stands now, each time through the loop &VNAME gets replaced. So the last value is the only one that could be used.
Good luck.
Ignore the earlier one:- This below is the updated code:-
%macro update();
%do i=9 %to 13;
%do j=1 %to 12;
%if %length(&i)=1 %then %let yr=200&i;
%else yr=20&i;
%if %length(&j)=1 %then %let mn=0&j.;
%else mn=&j;
%let vname=&yr&mn;
%end;
%end;
%mend;
%update;
You haven't described what issue you are having, however looking at the code I suspect it's where you assign the macro variable vname.
If you want to create a macro variable by combining 2 other macro variables then you need to use a double ampersand at the beginning.
%let vname=&&yr&mn;
The issue is that it says apprent symbol not resolved.
I want the output as :-
200901
200902
200903
.
.
.
201312
Have you tried the fix I suggested?
I've also just noticed that you've omitted %let from your %else statements.
Yes, i tried, Its not working !
%macro update();
data new1;
%do i=9 %to 13;
%do j=1 %to 12;
%if %length(&i)=1 %then %let yr=%eval(200&i);
%else %let yr=%eval(20&i);
%if %length(&j)=1 %then mnth=%str(0&j);
%else %let mnth=%eval(&j);
%let vname=&yr&mnth;
%put &vname.;
%end;
%end;
%mend;
%update;
ERROR:-
201312
NOTE 137-205: Line generated by the invoked macro "UPDATE".
690 mnth=0&j
____
22
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, ;, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT,
IN, LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, |, ||, ~=.
201312
201310
201311
132 The SAS System 09:51 Wednesday, June 5, 2013
201312
NOTE 137-205: Line generated by the invoked macro "UPDATE".
690 mnth=0&j
____
22
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, ;, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT,
IN, LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, |, ||, ~=.
691
Try also using the %strip command when creating the variables, to remove leading and trailing blanks. When you concatenate numeric variables, SAS converts them to character values (of minimum length 8 I believe), meaning that it will include blanks after the numbers.
You're now missing a %let between %then mnth=.....
That is ok but can you help me on this part:-
%if %length(&j)=1 %then mnth=%str(0&j);
%else %let mnth=%eval(&j);
As i want to have 0 been appended before a single digit to get 01, 02, 03...likewise..
so that i could append to the year like 200901, 200902..so on...
Hope you understand now!
%macro update();
data new1;
%do i=9 %to 13;
%do j=1 %to 12;
%if %length(&i)=1 %then %let yr=%eval(200&i);
%else %let yr=%eval(20&i);
%if %length(&j)=1 %then mnth=%str(0&j);
%else %let mnth=%eval(&j);
%let vname=&yr&mnth;
%put &vname.;
%end;
%end;
%mend;
%update;
This is also not working!
Use the z2. format which will put in the leading zero without having to use the length statement. Try something like the code below, I've used CATS instead of %strip so that the whole string can be created in 1 go.
(untested)
%let vname=%sysfunc(cats('20',%sysfunc(putn(&i.,z2.)),%sysfunc(putn(&j.,z2.))));
Not really sure what you actually want to achieve with your macro code. I hope below will give you some ideas/being of some help.
%macro update();
data new1;
%do i=9 %to 13;
%do j=1 %to 12;
%if %length(&i)=1 %then
%let yr=%eval(200&i);
%else %let yr=%eval(20&i);
%if %length(&j)=1 %then
%let mnth=%str(0&j);
%else %let mnth=%eval(&j);
%let vname=&yr&mnth;
%put &vname;
length yyyymm $6.;
yyyymm="&vname";
output;
%end;
%end;
run;
%mend;
%update;
data new2;
format date yymmn6.;
date='01jan2009'd;
length yyyymm $6;
do until(date>'01dec2013'd);
yyyymm=put(date,yymmn6.);
output;
date=intnx('month',date,1,'b');
end;
run;
You have already gotten a number of good suggestions here. Let me draw from them to summarize what you could do:
%macro update;
%local i j;
%do i=1 %to 12;
%do j=9 %to 13;
%let vname=20%sysfunc(putn(&j,z2))%sysfunc(putn(&i,z2));
%end;
%end;
%mend update;
Of course there must be more to your objective than this. The way the code stands now, each time through the loop &VNAME gets replaced. So the last value is the only one that could be used.
Good luck.
And I wonder why
%do j = 9 %to 13 would be preferable to %do year= 2009 %to 2013 or similar in the first place. The latter has a whole lot better of chance of working if your data ever includes values in the 1900's.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.