Dynamically choose name of macro to call? - macros

In SAS, the double/triple/etc ampersand can be used to dynamically choose which macro variable to resolve. Is there an equivalent syntax using double/triple/etc percents?
I tried %%%substr(&x,3) expecting the same resolution rules to be used (i.e. turn %% into %, then call the substring macro, then call the macro with the name of the result) but it is apparently invalid syntax.

You can use macro variable instead of fixed macro name, e.g.:
%let mname=test;
%macro test;
%put I am test.;
%mend;
%&mname

Related

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'"));

substr function with macro variable name

I am trying to use substr function in SAS macros like this:
%let hg=Name;
data gg_;
set sashelp.class;
gh=%substr(&hg,1,3);
run;
and also I tried
data gg_;
set sashelp.class;
gh=%sysfunc(substr(&hg,1,3));
run;
Here Name is the variable in sashelp.class
But I do not get the first three chars from Name variable into gh.
How do I do it?
You are mixing macro and data step logic.
Since it is a data step, use the SUBSTR() function, not %substr. If the macro variable consists of the text you want to extract then quote it, otherwise leave the macro variable unquoted.
gh=substr(&hg, 1, 3);
Note: edited to reflect comment.
If you are creating a dataset inside a macro function then you want to use the normal sas function so you just need to use substr() instead of %substr().
%let hg=Name;
data gg_;
set sashelp.class;
gh=substr(&hg,1,3);
run;

SAS Macro Variable Quoted Concatenation

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')));

Using SAS macros, is there a way to create variables with names that have spaces?

I'd like to use a macro to create a variable in my dataset. The variable name has spaces. Usually in SAS I would have to enclose the name with apostrophes: 'var_name'n . In macros, I've tried to mask the apostrophes using %(str):
For instance:
%macro test(varname);
%str(')&varname.%str('n)=""
%mend;
But this doesn't seem to work.
You can use a % symbol to escape the single quote and the %unquote function to resolve the reference, like so:
%macro test(varname);
%unquote(%str(%'&varname.%'n))="";
%mend;
Derived from Sample 25076: Resolve a macro variable within single quotes