SAS Macro Variable Quoted Concatenation - macros

I am debugging a macro I am writing that will treat a string as either a prefix or suffix of a dataset name based on user input. Then, the quoted result will be fed into another process downstream.
So if the user says Type=1 and provides the string 'data_', the output of the resulting macro variable will be 'data_%'.
I've tried a few different iterations of the below code, but can't quite get it....any help would be greatly appreciated. Thanks.
%let Type=1;
%let TableName=data_;
data _null_;
if &Type=1 then
call symput('qTableName',%unquote(%str(%')(cats(&TableName.,"%"))%str(%')));
else if &Type=2 then
call symput('qTableName',%unquote(%str(%')(cats("%",&TableName.))%str(%')));
run;
%put &qTableName;

Looks like you are trying to add single quotes to a macro variable.
%let TableName=data_;
%let qTableName='data_%';
So in a data step you can use CATQ().
data _null_;
call symputx('qTableName',catq('1a',cats(symget('TableName'),'%')));
run;
Or in simple macro code just use %bquote() to allow you to add ' and % without preventing macro variable expansion. But you probably want to remove the macro quoting it will cause.
%let qTableName=%unquote(%bquote('&TableName%'));
Or if you only want to add the % when &TYPE=1 then perhaps you could call the IFC() function. I believe that the %sysfunc() call will remove the macro quoting.
%let Type=1;
%let qTableName=%sysfunc(ifc(&type=1,%bquote('&TableName%'),%bquote('&TableName')));

Related

SAS %STR function not work

I am trying to use %STR function to mask % in the string. Code like this:
options symbolgen;
%let grp=%str(%C16F%);
%put group is &grp;
It doesn't work. Actually when I click the codes follow it, SAS does nothing. Nothing happens.
Do you know the reason? How to fix it?
Thank you for your help!
L.
The %STR() needs you to add extra % in front of second % in your string because otherwise it thinks you are trying use the % to escape the right parenthesis. That is why it appears nothing is running. The %LET statement is still waiting to see the end of the %str() function call and the terminal ;.
%let grp=%str(%C16F%%);
%put group is &grp;
I find it is easier to either use a data step and %superq() to make sure the value is quoted.
data _null_;
call symputx('grp','%C16F%');
run;
%let grp=%superq(grp);
Or use %qsysfunc() to call dequote() to remove the physical single quotes and add macro quoting.
%let grp=%qsysfunc(dequote('%C16F%'));

SAS MACRO Quoting issue : passing string with macro trigger as macro parameter

Is this possible to pass a string with macro trigger as the macro parameter?
Please see the example code below:
options mprint;
%let string5='%abc%def%';
%macro test(string);
data _null_;
call execute('%test2('||&string.||')');
run;
%mend;
%macro test2(string2);
data test3;
a=%str(%')&string2.%str(%');
run;
%mend;
%test(&string5);
This code ran successfully but it tried to invoke the macro %abc and %def, which resulted in warnings.
If I tried to put it into quoting to mask the string, it gave syntax error, as shown below:
options mprint;
%let string5='%abc%def%';
%macro test(string);
data _null_;
call execute('%test2('||%superQ(string)||')');
run;
%mend;
%macro test2(string2);
data test3;
a=%str(%')&string2.%str(%');
run;
%mend;
%test(&string5);
ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string, a numeric constant, a datetime constant, a missing value, arrayname, (, +, -, INPUT, NOT, PUT, ^, _NEW_, ~.
Is there a way to fix this without warnings?
Thanks in advance!
Try this:
%let string5='%abc%def%';
%macro test(string);
data _null_;
call execute('%test2('||%nrstr("&string.")||')');
run;
%mend;
%macro test2(string2);
data test3;
a=%nrquote(&string2.);
run;
%mend;
%test(&string5);
It is usually simple enough in the macro to protect against special characters. For example you can use the %superq() function to quote an existing macro variables value.
where name like %unquote(%str(%')%superq(parm1)%str(%'))
Or use the symget() function in a data step to get the value without needing to expand the macro at all.
pattern = quote(symget('parm1'),"'");
But the hard part is making the macro call. You need to protect the characters to get the macro call to run. You can use similar functions in the macro call.
One useful thing to do is to instruct users to pass the parameter value as a quoted string and then the macro code you can remove the quotes when they are not needed.
%macro mymacro(parm1=);
%let parm1=%qsysfunc(dequote(&parm1));
...
%mend;
%mymacro(parm1='fred%')
Or you could ask them to pass the value by name.
%macro mymacro(mvar=);
%local pattern ;
%let pattern=%superq(&mvar);
...
%mend ;
%let my_pattern=%qsysfunc(dequote('fred%'));
%mymacro(mvar=my_pattern)
If this is already working the way you want and you just want to suppress this one warning message, you could consider setting option nomerror; before you run the section of code in question and then setting it back again afterwards.
Just update the final solution I choose. I gave up the way to pass macro parameters between different macros, instead I passed the macro variable name as a string. Sample codes are as below:
options mprint;
%let string5='%abc%def%';
%macro test(string);
data _null_;
call execute('%test2('||&string.||')');
run;
%mend;
%macro test2(string2);
data test3;
a=&&&string2.;
run;
%mend;
%test('string5');

SAS Macro operations

I need to create sum of 4 variables multiple times each time with new set of variables. For e.g. A1=sum(a1,a2,a3,a4),B1=sum(b1,b2,b3,b4) & so on. So , I am trying to write a macro that will help me do it easily. Following is the code:
%macro SUM2(VAR1,var2,var3,VAR4);
data Subs_60_new;
set Subs_60;
substr(&var1,1,10)=sum(&var1,&var2,&var3,&var4);
run;
%mend sum2;
options mprint mlogic;sum2(ADDITIONAL_INFO_Q1,ADDITIONAL_INFO_Q2,ADDITIONAL_INFO_Q3,ADDITIONAL_INFO_Q4);
I am using SAS EG for the same & when I run the macro I get the following note:
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
& obviously when I try to execute the macro it throws an error.
Can some one help me out?
when calling a macro, you need to precede the macro name with a % symbol, eg as follows:
%macro SUM2(VAR1,var2,var3,VAR4);
data Subs_60_new;
set Subs_60;
substr(&var1,1,10)=sum(&var1,&var2,&var3,&var4);
run;
%mend sum2;
options mprint mlogic;
%sum2(ADDITIONAL_INFO_Q1,ADDITIONAL_INFO_Q2,ADDITIONAL_INFO_Q3,ADDITIONAL_INFO_Q4);
The NOTE is harmless. It is ERRORs and WARNINGs in general that you should be concerned with.
I'd point out that this will probably still throw an error, as you are trying to replace characters in a variable (&var1) that appears as though it should contain a numeric field (being part of a sum function). Given your description of what you are trying to achieve, I'd suggest adding the new variable name as another macro parameter - as follows:
%macro SUM2(VAR1,var2,var3,VAR4,varname);
data Subs_60_new;
set Subs_60;
&varname=sum(&var1,&var2,&var3,&var4);
run;
%mend sum2;
options mprint mlogic;
%sum2(ADDITIONAL_INFO_Q1,ADDITIONAL_INFO_Q2
,ADDITIONAL_INFO_Q3,ADDITIONAL_INFO_Q4
,MyNewVariable);

concatenation in sas using macro

I have two variables with me
%let End_of_month =%sysfunc(intnx(month,'&sysdate'd,-1,e),yymmdd10.);
%stamp =00:00:00
Now, i want to create a new variable
%time_stamp = '2016-06-19 00:00:00'
In order to make this variable , i am using cat function with sysfunc
%timestamp =%sysfunc(cat("'","&End_of_month".,"&stamp.","'"));
The above code is not giving me the desired results. Could somebody tell me how do I solve this using a %sysfunc.
I am not really sure how to use %str and nstr in this statement. Please let me know how can we solve cats, cat and catx in a macro.
Thanks
You initial 2 macro variable are wrong. Then End_of_month should rather be like this
%let End_of_month =%sysfunc(intnx(month,%str(%')&sysdate%str(%'d),-1,e),yymmdd10.);
%put &End_of_month;
OR
%let End_of_month =%sysfunc(intnx(month,%sysfunc(today()),-1,e),yymmdd10.);
%put &End_of_month;
Now coming to the creating a single quotation timestamp with 00:00:00 hr:min:sec afte the date with space as the delimiter, you don't have to use base SAS functions.. simply create the variable like below
%let timestamp=%str(%')&End_of_month 00:00:00%str(%');
%put &timestamp;
Also, %stamp means a macro call which has a definition and not a variable like you've mentioned in your questions.. similarly %timestamp= .. this is syntactically wrong in SAS.. %let timestamp= does macro variable creation and %timestamp would ideally call a timestamp named macro definition..I would suggest reading the SAS Macro Language Reference.
The best way to solve this problem (if it is something you do often) is to create your own format to do so. See this answer:
https://stackoverflow.com/a/24044451/214994
You do not need to use functions to concatenate macro variables. Just expand them where ever you need them in your code. Note also that you do not need to quote string literals in macro code. To the macro processor everything is a string literal.
%let end_of_month=%sysfunc(intnx(month,"&sysdate"d,-1,e),yymmdd10.);
%let time_stamp=&end_of_month 00:00:00;
Adding double quotes is simple.
%let time_stamp="&end_of_month 00:00:00";
Adding single quotes is a pain because the macro references are not resolved inside of single quotes. You could try using %bquote(), but then the value is macro quoted, which can cause trouble. So you might need to also add %unquote().
%let time_stamp=%unquote(%bquote('&end_of_month 00:00:00'));
I have found using the dequote() function is a simple way to introduce single quotes. Start with a string that has double quotes on the outside so that the macro references work and then use %sysfunc(dequote()) to remove the double quotes.
%let time_stamp=%sysfunc(dequote("'&end_of_month 00:00:00'"));

how to name dataset/variable using concatenation

I have a problem with SAS 9.2.
I'm writing a simple macro which creates dataset and name it according to the variables submitted and some other words/letters/signs, for example
%macro example(var1,var2);
data &var1 || '_word_' || &var2;
a=1;
run;
%mend;
Can anyone help?
Pipes are only for strings within SAS, not within SAS macro. So don't use them here.
SAS Macro does not interpret quotes as indicating a string, it will just read them, so leave out the quotes.
If you want to concatenate elements in macro, you just need to write them appended to each other.
To make clear where the macro variable name ends, append a dot.
This should work:
%macro example(var1,var2);
data &var1._word_&var2.;
a=1;
run;
%mend;