BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Sk4r
Obsidian | Level 7

I got this error because that dataset called data contains some questions where there are commas ( , symbol).

The only place of the macro makeReport where I use DES parameter is when giving a label.

My question is, how do I treat those questions that have commas in it, I tried using %str and %bquote, but I'm failing at some point to use the correct syntax, and SAS support website is kind of poor at explaing this kind of cases, because they apply those macros to string constants, not variables from a dataset.

Thank you very much. Part of the code is below.

 

%macro makeReport(N, DES);

......

proc tabulate data .............

LABEL="Question: &des"

..........

......

%mend;

 

data _null_;

set data;
call execute( ' %makeReport( ' ||number|| ', ' ||question|| ') ' );
run;

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

Since description is a text, it might make sense here to enclose it in quotes:

%macro makeReport(N, DES);

title "Question: &des.";

proc print data=sashelp.class;
run;

title;

%mend ;

data data;
infile cards dlm='|' dsd;
input number $ question :$50.;
cards;
1|"This has a, comma in the middle"
;
run;

data _null_;
set data;
call execute('%nrstr(%makeReport(' || number || ",'" || trim(question) || "'))");
run;

View solution in original post

6 REPLIES 6
SASKiwi
PROC Star

I've found that a good way to debug this or to use as a permanent solution is to build the macro statement separately like this:

 

data _null_;
set data;
execcmd =  '%makeReport('||number|| ', '||question|| ')';
call execute(execcmd);
put execcmd = ;
run;

 

ballardw
Super User

It would help to show the versions you tried with %str .

 

This works for my admittedly abbreviated makereport macro to assign a label to a variable.

%macro makeReport(N, DES);

data work.j;
   set work.class;
   label sex= "&des.";
run;
%mend ;


data junk;
   number = 3;
   question= "This has a, comma in the middle";
   length str $ 100;
   str = catx(',',cats('%makereport(',number),cats('%str(',question,'));'));
   call execute(str);
run;

I think that your example LABEL statement in proc tabulate was missing something, like the name of the variable to assign the label to perhaps?

Kurt_Bremser
Super User

Since description is a text, it might make sense here to enclose it in quotes:

%macro makeReport(N, DES);

title "Question: &des.";

proc print data=sashelp.class;
run;

title;

%mend ;

data data;
infile cards dlm='|' dsd;
input number $ question :$50.;
cards;
1|"This has a, comma in the middle"
;
run;

data _null_;
set data;
call execute('%nrstr(%makeReport(' || number || ",'" || trim(question) || "'))");
run;
Sk4r
Obsidian | Level 7

Thank you very much, sir.

I'd like to ask you something more, how did you structure those quotes? 

I'm still learning about SAS on my intership, that's why I'm kind of new in this enviroment.

 

Kurt_Bremser
Super User

Since we want to resolve the macro parameter in the macro, we will have to enclose it there in double quotes. This means it has to contain single quotes. In order to hand those over in the call execute, they are used in string literals enclosed in double quotes.

Tom
Super User Tom
Super User

The first thing in code generation (SAS macros or any other method) is know what code you want to generate.

The normal way to protect commas from the macro processor so they can be used in the value of a macro call is to use %STR().

%makeReport(N=100, DES=%str(sum of a,b,c));

Note: Just because you defined the macro to allow call by position doesn't mean you HAVE to call it without the parameter names.

So then your code generation just needs to add those extra characters.

call execute(cats(
'%nrstr(%makeReport)('
,number
, ', %str('
,question
,'))' 
));

Note: Wrapping the macro name inside of %NRSTR() will delay running the macro until the code stacked by CALL EXECUTE is pulled back to actually run. Otherwise the macro processor will run the macro immediately and stack up any code it generates to be run later.

 

You could also just change how your macro handles the data to allow you to use normal quotes to protect the embedded commas.

%macro makeReport(N, DES);
%let des=%qsysfunc(dequote(%superq(des)));
...

Also note that I find that using the PUT statement to generate code from data is usually a LOT easier than using CALL EXECUTE. Especially for generating macro calls and doubly so when the names of the data variables matches the names of the parameters.

filename code temp;
data _null_;
  set data;
  file code;
  put '%makeReport( '  N= ',' des= $quote. ')';
run;
%include code / source2 ;

So then you get a text file of code that looks like:

%makeReport(N=100,DES="sum a,b,c")
%makeReport(N=200,DES="Grand Total")
....

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 6 replies
  • 3389 views
  • 2 likes
  • 5 in conversation