I am using a data step (although I could use proc sql) to run through a list of names and generate a report.
the names are "Last Name, First Name".
I am getting: "ERROR: More positional parameters found than defined."
Here is sample code:
data namelist;
input ID GRP $4. NAME $25. ;
datalines;
01 ABCD Smith, John
02 WXYZ Jones, Dorothy
03 MNOP Garcia, Kimberly
;
%MACRO test_Report(ID, GRP, NAME);
%put ID;
%put &GRP;
%put &NAME;
%MEND;
data _NULL_;
set namelist; /* columns are ID Group and Name */
call execute( '%test_Report(' || strip(ID) || ',' || strip(GRP) || ',' || %bquote(NAME) || ');' );
run;
What am I missing? There has to be a simple way of doing this.
Thank you.
Stan
HI @SSTEAD slight adjustment to the syntax you used
data _NULL_;
set namelist; /* columns are ID Group and Name */
call execute
('%nrstr(%test_Report('||catx(',',ID,GRP,cat('%bquote(',NAME,')'))||'))');
run;
Some notes:
1. Your idea of %bquote(NAME) is very smart indeed. However you are better off delaying the execution of the macro call until after the datastep is complete.
2. Therefore you would need the %nrstr to delay the macro statements execution as the call can independently execute without having to bother with the datastep compiler.
3. In my humble opinion, it is better to not marry macro processor and execution unless absolutely needed, albeit the marriage most likely will end in a divorce.
You will need the macro invocation to mask the commas in the passed argument. This is most often done with %STR().
So you want the requested code to be executed to look like
%test_Report( <ID>, <GRP>, %STR(<LAST>,<FIRST>) )
Very often CALL EXECUTE statements are desired to have their submissions all occur after the DATA step completes. This can be accomplished by wrapping the submitted code in %NRSTR(). So the 'dispatching' data _null_ would be
data _NULL_; set namelist; /* columns are ID Group and Name */
* compute source code for macro invocation; macro_call_source_code = '%test_report(' || catx (',', ID, GRP, '%str(' || NAME || ')' ) /* wrap name in %STR source code to allow comma containing argument to be passed */ || ')' ;
* submit computed source code; call execute( '%nrstr(' || trim(macro_call_source_code) || ')' ); run;
If the macro is expected to get names that contain commas then write the macro in a way that it is expecting the values provided to have quotes.
%MACRO test_Report(ID, GRP, NAME);
%local name2;
%put ID value is &ID;
%put GRP value is &GRP;
%put NAME with quotes is &NAME;
%let name2=%sysfunc(dequote(&name));
%put NAME without qutoes is &NAME2;
%MEND;
Then provide the quotes in the call.
filename code temp;
data _NULL_;
set namelist; /* columns are ID Group and Name */
file code;
put '%test_Report(' id= ',' grp= ',' name= :$quote. ')';
run;
%include code / source2;
HI @SSTEAD slight adjustment to the syntax you used
data _NULL_;
set namelist; /* columns are ID Group and Name */
call execute
('%nrstr(%test_Report('||catx(',',ID,GRP,cat('%bquote(',NAME,')'))||'))');
run;
Some notes:
1. Your idea of %bquote(NAME) is very smart indeed. However you are better off delaying the execution of the macro call until after the datastep is complete.
2. Therefore you would need the %nrstr to delay the macro statements execution as the call can independently execute without having to bother with the datastep compiler.
3. In my humble opinion, it is better to not marry macro processor and execution unless absolutely needed, albeit the marriage most likely will end in a divorce.
You're welcome. Anyways, It was your solution that needed a slight adjustment. I wouldn't want to take that credit away from you.
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.