Hi,
I write a macro and now the step to call it.
I can list from line to line such as:
%mymacro(age=1);
%mymacro(age=2);
...
Instead I try 2 different method and the one with SQL and %put still works but generate all kind of error notice.
Can you tell me why and how to fix it?
data have; set sashelp.class;run;
%Macro mymacro(age = );
data _temp; set have;
if age=&age;run;
*if too small number of record --> no running code;
proc sql; select count(*) into: NOBS from _temp; quit;
%IF &NOBS>=4 %THEN %DO;
DATA A_&age; SET _temp; RUN;
%END;
%Mend;
proc sort data=have out=name_value (keep=age) nodupkey; by age;run;
*Method 1: work directly with file;
data _null_;
set name_value;
call execute(catt('%nrstr(%mymacro)(age=', age, ');'));
run;
*Method 2: create command first;
*create list of %mymacro(age= ) for macro run;
data name_value;set name_value;
string = catt('%mymacro(age=', age, ');');
run;
proc sql noprint;
select string into :codeline separated by ' ' from name_value; quit;
%put &codeline;
You are getting a timing issue with when the macro runs and when the code that the macro generates runs.
When you call it normally as the macro runs the code it generates runs. So the SQL code that sets NOBS macro variable runs and then the macro tests its values.
But when you use CALL EXECUTE() to run it, without the %NRSTR(), then the macro runs while CALL EXECUTE is pushing code onto the stack to run after the data step finishes. So the PROC SQL code gets generated, but it won't execute until after the data step finishes. So the %IF statement that is checking NOBS macro variable is either not finding the variable to finding some value that was already set before the data step (the one running the CALL EXECUTE) started running.
Check the difference in the lines with + that CALL EXECUTE shows in the log. When you protect the macro call you will see lines like:
+%mymacro(age=1);
When you don't then instead you see lines like:
+data _temp; +set have;
Similarly if you put a %PUT in front of the macro call then it will "eat" the DATA _TEMP; statement. So instead of running:
data _temp; set have;
You are asking SAS to run:
%put data _temp;
set have;
Now the SET statement has no DATA statement before it.
The other calls included into the macro variable should work fine.
Remove the %PUT.
Otherwise the code is:
%PUT %mymacro(age=11);;
Which isn't valid code. If you just have:
&codeLine;
It resolves to the following which is valid.
%mymacro(age=11);
FYI - you may want to add the NOPRINT option to your SQL code to avoid output to the RESULTS pane.
@hhchenfx wrote:
Hi,
I write a macro and now the step to call it.
I can list from line to line such as:
%mymacro(age=1);
%mymacro(age=2);
...
Instead I try 2 different method and the one with SQL and %put still works but generate all kind of error notice.
Can you tell me why and how to fix it?
data have; set sashelp.class;run; %Macro mymacro(age = ); data _temp; set have; if age=&age;run; *if too small number of record --> no running code; proc sql; select count(*) into: NOBS from _temp; quit; %IF &NOBS>=4 %THEN %DO; DATA A_&age; SET _temp; RUN; %END; %Mend; proc sort data=have out=name_value (keep=age) nodupkey; by age;run; *Method 1: work directly with file; data _null_; set name_value; call execute(catt('%nrstr(%mymacro)(age=', age, ');')); run; *Method 2: create command first; *create list of %mymacro(age= ) for macro run; data name_value;set name_value; string = catt('%mymacro(age=', age, ');'); run; proc sql noprint; select string into :codeline separated by ' ' from name_value; quit; %put &codeline;
You are getting a timing issue with when the macro runs and when the code that the macro generates runs.
When you call it normally as the macro runs the code it generates runs. So the SQL code that sets NOBS macro variable runs and then the macro tests its values.
But when you use CALL EXECUTE() to run it, without the %NRSTR(), then the macro runs while CALL EXECUTE is pushing code onto the stack to run after the data step finishes. So the PROC SQL code gets generated, but it won't execute until after the data step finishes. So the %IF statement that is checking NOBS macro variable is either not finding the variable to finding some value that was already set before the data step (the one running the CALL EXECUTE) started running.
Check the difference in the lines with + that CALL EXECUTE shows in the log. When you protect the macro call you will see lines like:
+%mymacro(age=1);
When you don't then instead you see lines like:
+data _temp; +set have;
Similarly if you put a %PUT in front of the macro call then it will "eat" the DATA _TEMP; statement. So instead of running:
data _temp; set have;
You are asking SAS to run:
%put data _temp;
set have;
Now the SET statement has no DATA statement before it.
The other calls included into the macro variable should work fine.
Very detail explanation!
Thanks a lot as usual, Tom.
HHC
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.