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

Hi Everyone,

I create a marco that skip iteration when dataset has small record.

So When I run manually 1 by 1 iteration, it works correctly create 3 datafile with N>=4.

 

When I try to run using execute(string), it fail to create right answer.

I have no idea why it happens that way.

 

My point is to check the %IF %THEN %DO so I try to simplify the problem

 

Any help is very much appreciated.


data have; set sashelp.class;run;

%Macro running_over_all_entry(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;

/*METHOD 1:		RUN ONE BY ONE*/
*this code correctly create only A_12, A_14, A_15;
%running_over_all_entry(age=11);
%running_over_all_entry(age=12);
%running_over_all_entry(age=13);
%running_over_all_entry(age=14);
%running_over_all_entry(age=15);
%running_over_all_entry(age=16);


/*METHOD 2:		CREATE a list for auto process;*/
proc sort data=have  out=name_value (keep=age) nodupkey; by age;run;

data macrocode;set name_value;
string =    catt('%running_over_all_entry(age=', age, ');');
*put string;run;

data _null_;set macrocode;
call execute(string);run;
1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

So you are trying to use CALL EXECUTE() to push code onto the stack to run after the data step finishes.

But you have not protected the macro calls so they are running during the CALL EXECUTE() statement and the resulting generated SAS code is being pushed onto the stack to execute instead of the macro call itself being pushed onto the stack.  This is causing the macro variable references to be resolved BEFORE the PROC SQL steps that set the macro variable have even run (since the PROC SQL steps are just sitting in the stack waiting to run after the current data step completes).

data _null_;
  set name_value;
  call execute(catt('%nrstr(%running_over_all_entry)(age=', age, ');'));
run;

 

 

View solution in original post

5 REPLIES 5
ballardw
Super User

@hhchenfx wrote:

Hi Everyone,

I create a marco that skip iteration when dataset has small record.

So When I run manually 1 by 1 iteration, it works correctly create 3 datafile with N>=4.

 

When I try to run using execute(string), it fail to create right answer.

I have no idea why it happens that way.

 


You really should describe how "it fails to create the right answer".

Are there errors in the log?: With macros involved run the code with options mprint symbolgen; to get more details of your generated code.

Post the code and log in a code box opened with the {i} to maintain formatting of error messages.

No output? Post any log in a code box.

Unexpected output? Provide input data in the form of a dataset, the actual results and the expected results. Data should be in the form of a data step. Instructions here: https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-dat... will show how to turn an existing SAS data set into data step code that can be pasted into a forum code box using the {i} icon or attached as text to show exactly what you have and that we can test code against.

 

With  the generic stuff out of the way:

 

DO NOT USE * line of stuff; style comments in macros.

Use either

%* line of stuff;

or

/* line of stuff */

comments. The * is not recognized as comment start in the macro language and may attempt to execute statements there.

Tom
Super User Tom
Super User

So you are trying to use CALL EXECUTE() to push code onto the stack to run after the data step finishes.

But you have not protected the macro calls so they are running during the CALL EXECUTE() statement and the resulting generated SAS code is being pushed onto the stack to execute instead of the macro call itself being pushed onto the stack.  This is causing the macro variable references to be resolved BEFORE the PROC SQL steps that set the macro variable have even run (since the PROC SQL steps are just sitting in the stack waiting to run after the current data step completes).

data _null_;
  set name_value;
  call execute(catt('%nrstr(%running_over_all_entry)(age=', age, ');'));
run;

 

 

hhchenfx
Barite | Level 11

OMG Tom,

Thank you again for saving me from time to time!!!!!

It will take time before I can understand the logic here.

HC

Tom
Super User Tom
Super User

Run it both ways and look that the lines in the SASLOG with a + at the beginning of the line that show the code that CALL EXECUTE() pushed onto the stack to run.  You will see that when you add the %NRSTR() macro quoting around the macro reference that the actual macro call shows up instead of the individual lines of code that the macro generates. 

hhchenfx
Barite | Level 11

Oh I see.

Thank you.

HC

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 5 replies
  • 749 views
  • 2 likes
  • 3 in conversation