BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
A_SAS_Man
Pyrite | Level 9

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         
1 ACCEPTED SOLUTION

Accepted Solutions
PaigeMiller
Diamond | Level 26

Your parentheses are wrong. It should be

 

%do %while (%scan(&month_list,&i) ne );
--
Paige Miller

View solution in original post

3 REPLIES 3
PaigeMiller
Diamond | Level 26

Your parentheses are wrong. It should be

 

%do %while (%scan(&month_list,&i) ne );
--
Paige Miller
Tom
Super User Tom
Super User

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?

Tom
Super User Tom
Super User

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;

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 3 replies
  • 2715 views
  • 1 like
  • 3 in conversation