Hi.
I've got problem apparently with some macro execution timing.
I've got macro A from which I execute macro C in a loop %do %while%.
I need to assure that macro C finished executing in iteration n before executing macro C in iteration n+1.
Now I get errors:
Line 696: ERROR: The macro C is still executing and cannot be redefined.
Line 697: ERROR: A dummy macro will be compiled.
and in the log i see that some iterations of macro C did not start at all.
Is there a way to force SAS to woit for macro execution?
Thanks for help.
Sounds like you have code like:
%macro a;
%macro c;
%mend c;
%c;
%mend a;
Move the definition of macro c outside of the definition of macro a.
%macro c;
%mend c;
%macro a;
%c;
%mend a;
i have;
%macro c;
%mend c;
%macro a;
%do %while ...
%c;
%end;
%mend a;
Next suspect is unbalanced quoting. Try starting SAS fresh. Does the macro A work the first time it is called?
Does it matter the values that are passed to it?
I am facing the same issue.
The macro 'c' works perfectly when stand alone, but when called in loop like -
%macro a;
%do i=1 %to 20;
%c;
%end;
%mend;
%a;
It gets stuck at some point and goes in never ending loop. And when forced 'STOP', any code I try to run that loop starts its run. Each time I had to close the project.
Hello,
Without knowing what the macro c contains, it is difficult to answer.
Could there be a conflict between macrovariables used in a and c ?
For instance, if you use the same counter i in both macros they have
to be declared as local.
macro 'c':
%macro combos(trxn=);
%let I=1;
data _ben_;
set _benef_(obs=&I. firstobs=&I.);
if senders gt 1 then do;
call symput('n_connect',senders);
end;
run;
proc surveyselect
data= _senders_ (where=(trxn_per_benef=compress(&trxn.))) out= _sen_ method=srs n= Compress(&n_connect.) noprint;
run;
data _tmp_;
merge _ben_ _sen_;
run;
data _tmp_;
set _tmp_;
n=_n_;
if missing(benef_id) then
do;
do until (not missing(benef_id));
n=n-1;
set _tmp_(keep=benef_id n_ben_f senders in_trxn trxn_per_sender) point=n; *second SET statement;
end;
end;
run;
%reset;
%if &upto. >= 100 %then %goto exit;
%fill_s: %do I=&I. %to &upto.;
/*Switch to Senders*/
%fill_senders;
%end;
%reset;
%if &upto. >= 100 %then %goto exit;
%do I=&I. %to &upto.;
/*Switch to Recipients*/
%fill_benefs;
%end;
%reset;
%if &upto. < 100 %then %goto fill_s;
%exit:
%mend;
%combos(trxn=1);
Macro 'a' :
%macro create_combos;
%do t=1 %to 20;
%combos(trxn=&t.);
%end;
%mend;
But then again the other two macros 'fill_benefs' and 'fill_senders' are using macro variables 'I' and 'TRXN', common to them but I need them as start from the value one ends like if 'I' ends in %fill_benefs at 15, I need the I starting from 16 in %fill_senders.
Please use the" little running man" icon to post code with proper identation.
%macro combos(trxn=);
%let I=1;
data _ben_;
set _benef_(obs=&I. firstobs=&I.);
if senders gt 1 then do;
call symput('n_connect',senders);
end;
run;
proc surveyselect
data= _senders_ (where=(trxn_per_benef=compress(&trxn.))) out= _sen_ method=srs n= Compress(&n_connect.) noprint;
run;
data _tmp_;
merge _ben_ _sen_;
run;
data _tmp_;
set _tmp_;
n=_n_;
if missing(benef_id) then
do;
do until (not missing(benef_id));
n=n-1;
set _tmp_(keep=benef_id n_ben_f senders in_trxn trxn_per_sender) point=n; *second SET statement;
end;
end;
run;
%reset;
%if &upto. >= 100 %then %goto exit;
%fill_s:
%do I=&I. %to &upto.;
/*Switch to Senders*/
%fill_senders;
%end;
%reset;
%if &upto. >= 100 %then %goto exit;
%do I=&I. %to &upto.;
/*Switch to Recipients*/
%fill_benefs;
%end;
%reset;
%if &upto. < 100 %then %goto fill_s;
%exit:
%mend;
%macro create_combos;
%do t=1 %to 20;
%combos(trxn=&t.);
%end;
%mend;
You still have loops calling macros that are black boxes to us. Do these macro modify the macrovariable upto ?
If not why testing the same condition several times. Insetad of using gotos, you should enlose treatments with do end
so that it's easier to follow the logic.
You initialize loops on macrovariable I with its own value &i. I guess the reset macro reinitialise I otherwise your second loop will then go from &upto+1 to &upto. which i doubt you really want.
Can you try to post a minimal executable example replicating the issue ?
As you said, in some cases I got stuck with "otherwise your second loop will then go from &upto+1 to &upto.". Thanks a lot!
The first line of the inner macro should give a good hint into the most likely source of your problem.
%macro combos(trxn=);
%let I=1;
Macro variable scoping.
If the environment that has called %COMBOS() already had a macro variable named I that it was using to control a loop then the first line in COMBOS just changed the value of that existing macro variable. Follow these simple rules and you should be ok.
The macro COMBOS has defined one local macro variable TRXN (all parameters are by definition local macro variables) but it is referencing these macro variables without defining their scope.
I
N_CONNECT
UPTO
And it is also calling other macros that might be lackadaisical in their use of macro variable scoping.
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.
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.