DATA Step, Macro, Functions and more

Marco skip iteration create different result for 2 methods

Accepted Solution Solved
Reply
Super Contributor
Posts: 503
Accepted Solution

Marco skip iteration create different result for 2 methods

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;

Accepted Solutions
Solution
‎01-31-2018 08:10 PM
Super User
Super User
Posts: 7,932

Re: Marco skip iteration create different result for 2 methods

[ Edited ]

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


All Replies
Super User
Posts: 13,293

Re: Marco skip iteration create different result for 2 methods


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.

Solution
‎01-31-2018 08:10 PM
Super User
Super User
Posts: 7,932

Re: Marco skip iteration create different result for 2 methods

[ Edited ]

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;

 

 

Super Contributor
Posts: 503

Re: Marco skip iteration create different result for 2 methods

OMG Tom,

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

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

HC

Super User
Super User
Posts: 7,932

Re: Marco skip iteration create different result for 2 methods

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. 

Super Contributor
Posts: 503

Re: Marco skip iteration create different result for 2 methods

Oh I see.

Thank you.

HC

☑ This topic is solved.

Need further help from the community? Please ask a new question.

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