Level 2 Practice: Using a %DO %UNTIL Loop
m104p11.sas
Modify the Storms macro to accept a space-separated list of years. Use a %DO %UNTIL loop and the %SCAN macro function to generate a report for each year in the list.
here is the code I have executed that is giving an error message (shown below the code):
%macro storms(year);
%let i=1;
%let yr=%scan(&year, &i);
%do %Until (&yr eq) ;
title "&yr Storms";
proc means data=mc1.storm_final n min mean max maxdec=0;
var MaxWindMPH MinPressure;
where season=&yr;
run;
%let i = %eval(&i+1);
%let yr=%scan(&year, &i);
%end;
title;
%mend storms;
%storms
Your code is truncated perhaps??
You defined the macro STORMS to accept an input parameter. But you did not pass it any value for the parameter in your call to the macro. Try either one of these macro calls instead.
%storms(2019 2020)
%storms(year=2019 2020)
Remember that you can pass values to a macro by NAME even for parameters that you defined to allow the values to passed by position.
Also your code is NOT expecting a space delimited list. Instead it is expecting a list that is delimited by any of the default delimiters that the %SCAN() function uses.
If you use the %SCAN function with only two arguments, then the default delimiters depend on whether your computer uses ASCII or EBCDIC characters.
blank ! $ % & ( ) * + , - . / ; < ^¦
In ASCII environments that do not contain the ^ character, the %SCAN function uses the ~ character instead.
blank ! $ % & ( ) * + , - . / ; < ¬ | ¢¦
To make it use only SPACE as the delimiter update this line (in both places it appears) in your macro definition.
%let yr=%scan(&year, &i, %str( ));
The first thing I see is that your code does not provide a space-delimited list of years for the macro to work with. If you provide some values like this:
%storms(1980 1990 2000 2010)
your macro will generate a report for each year.
Another example of using a macro when you don't need a macro. You can obtain the same without macros, using a BY statement in PROC MEANS. In other words, a terrible question, and the student comes away from this class thinking "When I need to get statistics by year, I can do this via a macro!" which is completely the wrong lesson to learn.
Hi,
To see what the macro is generating you can submit the following line of code before invoking the macro:
options mprint;
Then you can see if there are any issues with the generated code.
Also, if variable season is character then remember to use double quotes around the &yr value in the where statement, i.e.:
where season="&yr";
If you're still having issues then please share the whole log (with the mprint option) by copying and then pasting it here using the Insert Code icon "</>".
Thanks & kind regards,
Amir.
Your code is truncated perhaps??
You defined the macro STORMS to accept an input parameter. But you did not pass it any value for the parameter in your call to the macro. Try either one of these macro calls instead.
%storms(2019 2020)
%storms(year=2019 2020)
Remember that you can pass values to a macro by NAME even for parameters that you defined to allow the values to passed by position.
Also your code is NOT expecting a space delimited list. Instead it is expecting a list that is delimited by any of the default delimiters that the %SCAN() function uses.
If you use the %SCAN function with only two arguments, then the default delimiters depend on whether your computer uses ASCII or EBCDIC characters.
blank ! $ % & ( ) * + , - . / ; < ^¦
In ASCII environments that do not contain the ^ character, the %SCAN function uses the ~ character instead.
blank ! $ % & ( ) * + , - . / ; < ¬ | ¢¦
To make it use only SPACE as the delimiter update this line (in both places it appears) in your macro definition.
%let yr=%scan(&year, &i, %str( ));
Catch the best of SAS Innovate 2025 — anytime, anywhere. Stream powerful keynotes, real-world demos, and game-changing insights from the world’s leading data and AI minds.
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.