I am attempting to write a do while loop that will iterate over a list of values within a macro and am getting a strange result. I have based the structure off of other examples but can't find anything related to this error. I start with this below:
proc sql noprint;
select distinct Year_Month format=date9. into : month_list separated by ' '
from string_all
where Year_Month >= '01JAN2021'd
;
quit;
%macro historical_calcs();
%local i next_month;
%do %while (%scan(&month_list),&i) ne );
%let next_month=%scan(&month_list, &i);
proc sql;
create table strings as
select distinct string into : string_list separated by ' '
from strings_all
where Year_Month=&next_month
And
string is not missing
;
quit;
%let i = %eval(&i + 1);
%end;
%mend;
I get an error saying "Expected semicolon not found after WHILE clause" and "A dummy macro will be compiled". What I am I missing about the structure of my do while part?
Edit: So I included the rest of the code and I've also included the log statement below.
GOPTIONS ACCESSIBLE; 26 27 %macro historical_calcs(); 28 %local i next_month; 29 %do %while (%scan(&month_list),&i) ne ); ERROR: Expected semicolon not found after WHILE clause. ERROR: A dummy macro will be compiled. 30 %let next_month=%scan(&month_list, &i); 31 32 proc sql; 33 create table strings as 34 select distinct strings into : string_list separated by ' ' 35 from strings_all 36 where Year_Month=&next_month 37 And 38 string is not missing 39 ; 40 quit; 41 42 %let i = %eval(&i + 1); 43 %end; 44 %mend; 45
Your parentheses are wrong. It should be
%do %while (%scan(&month_list,&i) ne );
Your parentheses are wrong. It should be
%do %while (%scan(&month_list,&i) ne );
Fix the first error.
27 %macro historical_calcs(); 28 %local i next_month; 29 %do %while (%scan(&month_list),&i) ne ); ERROR: Expected semicolon not found after WHILE clause. ERROR: A dummy macro will be compiled. 30 %let next_month=%scan(&month_list, &i);
At line 29 you have unbalanced parentheses. you have two open parens and three closing parens.
Also there is a logic error. When line 29 runs there is no way that the macro variable I can have a value yet.
Perhaps you need to set it to 1 before the %DO statement?
Why are you trying to use DO WHILE for simple iterative DO loop?
Other issues:
proc sql noprint;
select distinct Year_Month into :month_list separated by ' '
from string_all
where Year_Month >= '01JAN2021'd
;
%let n_months=&sqlobs;
quit;
%macro historical_calcs();
%local i next_month;
%do i=1 %to &n_months;
%let next_month=%scan(&month_list, &i);
proc sql;
create table strings as
select distinct quote(trim(string)) into :string_list separated by ' '
from strings_all
where Year_Month=&next_month
and string is not missing
;
%let n_strings = &sqlobs;
quit;
%put &=i &=next_month &=n_strings &=string_list ;
%end;
%mend;
If you did want to mimic an iterative DO loop like:
%do i=<start value> %to <end value> %by <step value>;
...
%end;
with a DO WHILE loop then the pattern should be something like this.
%let i=<start value>;
%do %while (&i <= <end value>);
....
%let i=%eval(&i + <step value>);
%end;
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.