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;
Available on demand!
Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.
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.