SAS, when running a macro in the data step with dosubl() function failed to pass the parameter as expected

132 views Asked by At

a macro works good when running when it is used in general sense, %Count(inds=ADRS, paramcd=OVRLRESP, avalc=SD) ; then I wish to run this macro from a table named NL like below: paramcd avalc OVRLRESP SD OVRLRESP PD

    data _null_ ;
    set nl ;
    cmd= "%Count(inds=adrs, paramcd='"||strip(paramcd)||"', avalc='"||strip(avalc)||"');"  ;
    rc2=dosubl(cmd); 
    run;

Reading the log, there are these message:

MLOGIC(COUNT):  Beginning execution.
MLOGIC(COUNT):  Parameter INDS has value adrs
MLOGIC(COUNT):  Parameter PARAMCD has value '"||strip(paramcd)||"'
MLOGIC(COUNT):  Parameter AVALC has value '"||strip(avalc)||"'
;

Would anyone suggest me what wrong I have made?

2

There are 2 answers

0
Richard On

Don't double quote the text used to construct the macro call. When in double quotes the macro will be called (attempted) as the step is getting delivered to the supervisor for compilation.

Example:

Single quote the macro call in the statement being assembled as source code text.

data _null_ ;
    set nl ;
    cmd= '%Count' || "(inds=adrs, paramcd='"||strip(paramcd)||"', avalc='"||strip(avalc)||"')"  ;
    rc2=dosubl(cmd); 
run;

For clarity you can use a tokenized template and transtrn to resolve the template

length cmd $1000;
cmd = '%Count(inds=adrs, paramcd=''#parmcd#'', avalc=''#avalc#'')' ;
cmd = transtrn(cmd, '#parmcd#', strip(parmcd)) ;
cmd = transtrn(cmd, '#avalc#', strip(avalc)) ;
rc = dosubl(trim(cmd));
0
Tom On

You are trying to put the text that the macro %COUNT() emits as the contents of the CMD character variable. Here is an example of what you are doing:

277  %macro count(inds,paramcd,avalc);
278  %put &=inds &=paramcd &=avalc;
279  * This macro only emits this comment statement ;
280  %mend count;
281
282  data _null_ ;
283    paramcd='xxx';
284    avalc='yyy';
285    cmd= "%Count(inds=adrs, paramcd='"||strip(paramcd)||"', avalc='"||strip(avalc)||"');"  ;
INDS=adrs PARAMCD='"||strip(paramcd)||"' AVALC='"||strip(avalc)||"'
286    put (_all_) (=/);
287  run;


paramcd=xxx
avalc=yyy
cmd=* This macro only emits this comment statement ;;
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

I think instead you want to write the CALL to the macro into the character variable.

cmd= cats('%Count(inds=adrs, paramcd=',paramcd,', avalc=',avalc,')')  ;

Which makes more sense.

288  %macro count(inds,paramcd,avalc);
289  %put &=inds &=paramcd &=avalc;
290  * This macro only emits this comment statement ;
291  %mend count;
292
293  data _null_ ;
294    paramcd='xxx';
295    avalc='yyy';
296    cmd= cats('%Count(inds=adrs, paramcd=',paramcd,', avalc=',avalc,')')  ;
297    put (_all_) (=/);
298  run;


paramcd=xxx
avalc=yyy
cmd=%Count(inds=adrs, paramcd=xxx, avalc=yyy)

And if we add back the call to DOSUBL() we get:

304  options mlogic mprint;
305  data _null_ ;
306    paramcd='xxx';
307    avalc='yyy';
308    cmd= cats('%Count(inds=adrs, paramcd=',paramcd,', avalc=',avalc,')')  ;
309    rc = dosubl(trim(cmd));
310    put (_all_) (=/);
311  run;

MLOGIC(COUNT):  Beginning execution.
MLOGIC(COUNT):  Parameter INDS has value adrs
MLOGIC(COUNT):  Parameter PARAMCD has value xxx
MLOGIC(COUNT):  Parameter AVALC has value yyy
MLOGIC(COUNT):  %PUT &=inds &=paramcd &=avalc
INDS=adrs PARAMCD=xxx AVALC=yyy
MPRINT(COUNT):   * This macro only emits this comment statement ;
MLOGIC(COUNT):  Ending execution.

paramcd=xxx
avalc=yyy
cmd=%Count(inds=adrs, paramcd=xxx, avalc=yyy)
rc=0