- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Your parentheses are wrong. It should be
%do %while (%scan(&month_list,&i) ne );
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Your parentheses are wrong. It should be
%do %while (%scan(&month_list,&i) ne );
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Why are you trying to use DO WHILE for simple iterative DO loop?
Other issues:
- Use the automatic macro SQLOBS to capture the number of months found.
- Do not format the date values. Or if you do then make sure to reference the value appropriately when using the strings pulled from the macro variable with the list of values.
- Unless you are positive your STRING variable never contains spaces you should quote the values before generating a space delimited list of the values.
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;