Hi all,
%macro test1(s);
%do i=1 %to %sysfunc(countw(&s,%str( ),q));
%let varname =%scan(&s,&i.);
call execute('%freq(DATASET = b2,VAR=&varname.,_,OUTDS=d_&varname.)');
%end;
%mend test1;
%test1(a b c d e f g) ; /* like a b c d e f g , I have 35 variables to pass */
I'm getting an error :
VARNAME=a
NOTE: Line generated by the invoked macro "TEST1".
37 call execute('%freq(DATASET = b2,VAR=&varname.,
37 OUTDS=d_&varname.)');
ERROR 180-322: Statement is not valid or it is used out of proper order.
VARNAME=b
NOTE: Line generated by the invoked macro "TEST1".
37 call execute('%freq(DATASET = b2,VAR=&varname.,
37 OUTDS=d_&varname.)');
ERROR 180-322: Statement is not valid or it is used out of proper order.
ERROR 180-322: Statement is not valid or it is used out of proper order.
VARNAME=c
NOTE: Line generated by the invoked macro "TEST1".
37 call execute('%freq(DATASET = b2,VAR=&varname.,
37 OUTDS=d_&varname.)');
ERROR 180-322: Statement is not valid or it is used out of proper order.
---------------------------------------------------------------------
Modify your call execute like this:
call execute(cats('%nrstr(%freq(DATASET = b2,VAR=',"&varname.,_,OUTDS=d_&varname.))"));
The %nrstr prevents timing problems caused by mixed Base SAS/macro code, and the double quotes around the second part of the call allow resolution of macro variable &varname. Macro triggers are not resolved when enclosed by single quotes.
Please post
Hello @sahoositaram555
The post in this thread by @FreelanceReinh is the answer you want.
I think that you're keeping crucial parts of the log from us, as you use one positional parameter in the %freq call, while all others are named. That usually does not work as intended.
I've stripped your code down to the bare essentials, and it works:
%macro freq(dataset=,var=,outds=);
%put dataset=&dataset;
%put var=&var;
%put outds=&outds;
%mend;
%macro test1(s);
%do i=1 %to %sysfunc(countw(&s,%str( ),q));
%let varname =%scan(&s,&i.);
call execute(cats('%nrstr(%freq(DATASET = b2,VAR=',"&varname.,OUTDS=d_&varname.))"));
%end;
%mend test1;
data _null_;
%test1(a b c d e f g)
run;
Take this code and expand from there.
Before putting code in a macro, make sure that it works without all the macro code.
You're missing a comma in:
call execute(cats('%nrstr(%freq(DATASET = b2,TRT=trt, TRTFMT =_NONE_ ,BYVAR = _NONE_,FMTVAR= _NONE_,COND= _NONE_,PCTTYPE= COL,P= _NONE_,DENOMNODISP = _NO_,
delALLDS= _YES_,MAXnumLEN= 6,clopper_pearson = _NONE_
VAR='
, /*need comma here*/
"&varname.,_,OUTDS=d_&varname.))"));
run;
But more importantly, you don't need call execute here, and it makes the code harder to read.
You've already written a macro %DO loop. Within that loop you can call %FREQ. You don't need a DATA STEP and CALL EXECUTE, since you're not reading any data.
Below is an example like yours, modified to just call %FREQ within the %DO loop:
%macro test1(data=,var=);
%local i varname;
%do i=1 %to %sysfunc(countw(&var,%str( ),q));
%let varname =%scan(&var,&i,%str( ),q);
%put &=i &=varname ;
%freq(data =&data,VAR=&varname)
%end;
%mend test1;
%macro freq(data=,var=) ;
proc freq data=&data ;
tables &var ;
run ;
%mend freq ;
options mprint ;
%test1(data=sashelp.shoes,var=Product Region Returns)
Hi @sahoositaram555,
CALL EXECUTE can only be used in a DATA step. So, if macro test1 is not called within a DATA step, don't use CALL EXECUTE, but simply call the inner macro as usual: %freq(DATASET=...)
(no semicolon required).
The underscore (positional parameter between keyword parameters VAR and OUTDS? Not occurring in your log excerpt, though.) is likely to produce further error messages, but these will have nothing to do with the outer macro.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.