%macro test(n);
%if &n=1 %then a;
%if &n=2 %then b;
%mend test;
%put %test(1)zz; /* produces azz */
data;
azz=0;
v1 = %test(1)zz; /* produces error */
run;
Hi!
It seems that when you build names like this, with macros, the result is not considered as one name by sas. Instead it's considered as two names that are concatenated. But if we put the expression inside of some macro function, we can put the parts together again. For example:
data;
azz=0;
v1 = %unquote(%test(1)zz);
run;
%then a;
What are you expecting that portion of your code to do?
In the data step, I want to execute the line
v1 = azz;
So with
%then a;
I'm expecting the macro to return the text 'a'. It does this when I use the macro in the %put statement.
I cant test anything now, but would guess that it revolves with spaces so what you actually you see is
a zz.
You can look into the vvaluex function regardless because I think that's close to what you're looking for.
I alos would have expected this to work.
This method works:
%macro test(n);
%global varname;
%if &n=1 %then %let varname=a;
%if &n=2 %then %let varname=b;
%mend test;
data test;
azz = 0;
bzz = 1;
%test(1);
v1 = &varname.zz;
%test(2);
v2 = &varname.zz;
run;
Back to the basics of tokens....SAS(R) 9.4 Macro Language: Reference, Third Edition
As the compiler runs you have those words/tokens. the %test(1) is a nice token and gets resolved. Than what you have caused is a change in the token of the datastep.. expecting azz as the next one token for the datastep. that is moving the pointer back to the beginning where the macro started.
It looks like that pointer for the next token is positioned AFTER the text insertion. We could see this as unwanted unexpected behavior. Should be easy to be solved by SAS. The only hurdle will be accepting this as a failure/defect/problem by SAS TS. Did you made a call to those?
The most easily answer of them is getting "works as designed"..... (sighhh)
Hi!
It seems that when you build names like this, with macros, the result is not considered as one name by sas. Instead it's considered as two names that are concatenated. But if we put the expression inside of some macro function, we can put the parts together again. For example:
data;
azz=0;
v1 = %unquote(%test(1)zz);
run;
You need put quote around it .
%macro test(n);
%if &n=1 %then a ;
%if &n=2 %then b ;
%mend test;
%put %test(1)zz; /* produces azz */
data x;
azz=0;
v1 ="%test(1)zz"; /* produces error */
run;
Message was edited by: xia keshan
SAS UE
1 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
42 ;
43
44 %macro test(n);
45 %if &n=1 %then %do; a %end;
46 %if &n=2 %then %do; b %end;
47 %mend test;
48
49 %put %test(1)zz; /* produces azz */
azz
50
51 data;
52 azz=0;
53 v1 = %test(1)zz; /* produces error */
53 v1 = %test(1)zz; /* produces error */
__
22
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT, IN,
LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, |, ||, ~=.
54 run;
The error message is seeming the (1) being seen by the datastep not removed by macro-processing. Changing the code into:
1 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
42 ;
43
44 %macro test(n);
45 %if "&n"="" %then %do; a %end;
46 %if "&n"="1" %then %do; a %end;
47 %if "&n"="2" %then %do; b %end;
48 %mend test;
49
50 %put %test(1)zz; /* produces azz */
azz
51
52 data;
53 azz=0;
54 v1 = %test.zz; /* produces error */
__
388
ERROR 388-185: Expecting an arithmetic operator.
__
200
ERROR 200-322: The symbol is not recognized and will be ignored.
You cannot leave the () away as it will fail to recognize the macro-name a dot as separation isn't valid syntax as the macro call is not a macro variable.
Sorry. I just push my code too quickly. See the code updated.
Xia, he wants to parametrize the name of the variable whose value should go into v1. So v1 should be numeric and have 0 (the value of azz) as value.
Oh. I never realize why OP would want do this . It is so weird .
%macro test(n);
%if &n=1 %then a ;
%if &n=2 %then b ;
%mend test;
%put %test(1)zz; /* produces azz */
data x;
azz=0;
v1 =%nrbquote(%test(1)zz); /* produces error */
run;
Xia, indeed it is weird to parameterize a variables names. There are many more ways (arrays?) to do something smart.
That is bringing us to the question why would BruceBad want to do this. It is some part of his mind probably doing something in many many steps.
I like Kurt's code that should be OK too and more elegant ..
What output values are you expecting to see in variable V1? Does V1 need to contain a character value representing the name of a variable or does V1 need to contain the value of a variable name?
Kurts code:
%macro test(n);
%global varname;
%if &n=1 %then %let varname=a;
%if &n=2 %then %let varname=b;
%mend test;
data test;
azz = 0;
bzz = 1;
%test(1);
v1 = &varname.zz;
%test(2);
v2 = &varname.zz;
run;
proc print data=test(obs=7);
run;
Obs azz bzz v1 v2
1 0 1 0 1
XIA's code:
%macro test(n);
%if &n=1 %then a ;
%if &n=2 %then b ;
%mend test;
%put %test(1)zz; /* produces azz */
data x;
azz=0;
v1 ="%test(1)zz";
run;
proc print data=x(obs=7);
run;
Obs azz v1
1 0 azz
%macro test(n);
%if &n=1 %then a;
%if &n=2 %then b;
%mend test;
%put %test(1)zz; /* produces azz */
data data4;
azz=0;
v1 = %unquote(%test(1)zz); /*does not produce an error. V1 contains the value of variable AZZ */
run;
proc print data=data4;run;
Obs azz v1
1 0 0
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!
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.