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

Hi There,

 

I'm trying to run a set of macros(some are nested) in loop even when one/all of the occurrence fails/aborted conditionally.

 

So I decided to use CALL EXECUTE with %NRSTR option as below. 

 

In the below code the main macro is XYZ1 which calls XYZ2.  The XYZ2 macro is conditionally aborted. My need is to continue running the next occurance of XYZ1 even when the XYZ2 fails/aborts. But for some reason, the entire run stops when the code encounters %abort statement in XYZ2. I also tried %abort cancel in place of %abort in XYZ2.

 

I'm running the below program using SASEG.

%Macro XYZ1(mi_stopCount);
	%local i j k;
	%do i = 1 %to 5;
		%put XYZ1 &i;
		%XYZ2(&mi_stopCount.);
		%put -------------;
	%end;
%Mend;
%Macro XYZ2(mi_stopCount);
	%local i j k;
	%do i = 1 %to 5;
		%put XYZ2 &i;
		%if &i = &mi_stopCount. %then %do;
			%put XYZ2 Aborting at &i.;
			%abort;
		%end;
	%end;
%Mend;
%Macro Driver();
	options nomlogic nomprint nosymbolgen nonotes;
	%local i j k;
	data _null_;
		retain s_no;
		set sashelp.class end=eof;
		if _n_ = 1 then s_no = 0;
		s_no = s_no + 1;
		put 'Before calling macro = ' s_no;
		call execute('%nrstr(%xyz1('||strip(4)||'));');
		put 'After calling macro  = ' s_no;
		if s_no = 2 then stop;
	run;
%Mend;
%Driver

 

Note: I was able to do this earlier with the same approach but I'm missing something now. 

 

Any help would be greatly appreciated. 

 

Thanks,

Ramesh

1 ACCEPTED SOLUTION

Accepted Solutions
Ramesh_165
Obsidian | Level 7

I was able to fix the problem by removing the macro wrapper from the data step.

 

In the below code, I've removed %Macro Driver(); , %Mend; and %Drivers statements.

 

%Macro XYZ1(mi_stopCount);
	%local i j k;
	%do i = 1 %to 5;
		%put XYZ1 &i;
		%XYZ2(&mi_stopCount.);
		%put -------------;
	%end;
%Mend;
%Macro XYZ2(mi_stopCount);
	%local i j k;
	%do i = 1 %to 5;
		%put XYZ2 &i;
		%if &i = &mi_stopCount. %then %do;
			%put XYZ2 Aborting at &i.;
			%abort;
		%end;
	%end;
%Mend;

	data _null_;
		retain s_no;
		set sashelp.class end=eof;
		if _n_ = 1 then s_no = 0;
		s_no = s_no + 1;
		put 'Before calling macro = ' s_no;
		call execute('%nrstr(%xyz1('||strip(4)||'));');
		put 'After calling macro  = ' s_no;
		if s_no = 2 then stop;
	run;

Thanks,

Ramesh

View solution in original post

4 REPLIES 4
novinosrin
Tourmaline | Level 20

If my understanding is correct, no matter you declare macro var i as local separately, the i in the inner macro call is local to both inner and outer macro. Therefore it aborts. If you remove the %local in the outer macro, that would still abort. 

 

So I tested changing the index variable i to t in the outer macro to see if my understanding is correct, and


dm log 'clear';
%Macro XYZ1(mi_stopCount);
	%local i j k;
	%do t = 1 %to 5;
		%put XYZ1 t=&t;
		%XYZ2(&mi_stopCount.);
		%put -------------;
	%end;
%Mend;
%Macro XYZ2(mi_stopCount);
	%local i j k;
	%do i = 1 %to 5;
		%put XYZ2 i=&i;
		%if &t = &mi_stopCount. %then %do;
			%put XYZ2 Aborting at &i.;
			%abort;
		%end;
	%end;
%Mend;
%Macro Driver();
	options nomlogic nomprint nosymbolgen nonotes;
	%local i j k;
	data _null_;
		retain s_no;
		set sashelp.class end=eof;
		if _n_ = 1 then s_no = 0;
		s_no = s_no + 1;
		put 'Before calling macro = ' s_no;
		call execute('%nrstr(%xyz1('||strip(4)||'));');
		put 'After calling macro  = ' s_no;
		if s_no = 2 then stop;
	run;
%Mend;
%Driver
 
Before calling macro = 1
After calling macro  = 1
Before calling macro = 2
After calling macro  = 2
1   +  %xyz1(4);
XYZ1 t=1
XYZ2 i=1
XYZ2 i=2
XYZ2 i=3
XYZ2 i=4
XYZ2 i=5
-------------
XYZ1 t=2
XYZ2 i=1
XYZ2 i=2
XYZ2 i=3
XYZ2 i=4
XYZ2 i=5
-------------
XYZ1 t=3
XYZ2 i=1
XYZ2 i=2
XYZ2 i=3
XYZ2 i=4
XYZ2 i=5
-------------
XYZ1 t=4
XYZ2 i=1
XYZ2 Aborting at 1
ERROR: Execution terminated by an %ABORT statement.
ChrisNZ
Tourmaline | Level 20

>  My need is to continue running the next occurance of XYZ1 even when the XYZ2 fails/aborts

 

Would using  %return;  instead of  %abort;  not serve this purpose?

Ramesh_165
Obsidian | Level 7

Thanks for replying. The code I posted is an example code, and %return may work for the example code I posted.

My actual program has other macros calls after the macro that could %abort. So using %return would allow the flow of the program to call other macros which in my case is not needed. 

Ramesh_165
Obsidian | Level 7

I was able to fix the problem by removing the macro wrapper from the data step.

 

In the below code, I've removed %Macro Driver(); , %Mend; and %Drivers statements.

 

%Macro XYZ1(mi_stopCount);
	%local i j k;
	%do i = 1 %to 5;
		%put XYZ1 &i;
		%XYZ2(&mi_stopCount.);
		%put -------------;
	%end;
%Mend;
%Macro XYZ2(mi_stopCount);
	%local i j k;
	%do i = 1 %to 5;
		%put XYZ2 &i;
		%if &i = &mi_stopCount. %then %do;
			%put XYZ2 Aborting at &i.;
			%abort;
		%end;
	%end;
%Mend;

	data _null_;
		retain s_no;
		set sashelp.class end=eof;
		if _n_ = 1 then s_no = 0;
		s_no = s_no + 1;
		put 'Before calling macro = ' s_no;
		call execute('%nrstr(%xyz1('||strip(4)||'));');
		put 'After calling macro  = ' s_no;
		if s_no = 2 then stop;
	run;

Thanks,

Ramesh

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
  • 4 replies
  • 841 views
  • 0 likes
  • 3 in conversation