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
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
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.
> 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?
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.
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 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.