Is there a way to reference a non-existing macro variable in a parameter of a macro call without getting a warning of a non-declared macro variable?
E.g. %report (footnotes = &line | footnote1 | footnote2, ...).
I have to use a standard macro which declares line as global and sets it according to the linesize value. I can't declare it as global before calling the macro, then it would be resolved in the call directly, and the value set in the macro is not reflected. Note that the macro works correctly, because &line is not resoved in the call but only later after line is defined within the macro and the parameter footnotes is used after.
I see 2 possible solutions to the problem:
1. somehow preventing &line to be resolved during the call but enabling later resolution. Quoting does not help here because I can't change the macro to add an %unquote call.
2. finding a macro macro option similar to the system option var_init_chk = nonote, but I didn't find something like that.
If you really really need to stick &LINE into your call then here is a trick that does it.
&&%upcase(line)
Example:
%macro test(x);
%let line=Set later;
%put ACTUAL X=%superq(x);
%put EFFECTIVE &=x;
%mend test;
%let line=Set earlier;
%test(x=&line);
%test(x=&&%upcase(line));
I don't know of such an option, but ...
Couldn't you just remove &LINE from the macro call, and change the interior logic of the macro to add it back in once the value has been set? If you are really not allowed to fiddle with %REPORT at all, perhaps you could construct:
%macro report2 (footnotes_without_line=);
%report (footnotes=&footnotes_without_line)
%* Additional logic to add back in the value of &LINE;
%mend report2;
However, that may not help since %REPORT finishes before you get to adjust the value of &FOOTNOTES.
Use a wrapper macro to detect the presence of a macro variable with %symexist:
%macro checkvar(varname);
%if %symexist(&varname) %then &&varname; %else %str( );
%mend;
title "%checkvar(xxx)";
proc print data=sashelp.class (obs=1) noobs;
run;
%let xxx=this is a test;
title "%checkvar(xxx)";
proc print data=sashelp.class (obs=1) noobs;
run;
%symdel xxx;
The first proc print has an empty title, no WARNINGs in the log.
I don't understand what the problem is.
It sounds like you want to conditionally update the value of the FOOTNOTES macro variable to contain the value of the LINE macro variable.
%macro report (footnotes .... );
%if %symexist(line) %then footnotes=&line|&footnotes;
....
%mend;
%report(footnotes=footnote1 | footnote2, ...).
If you really really need to stick &LINE into your call then here is a trick that does it.
&&%upcase(line)
Example:
%macro test(x);
%let line=Set later;
%put ACTUAL X=%superq(x);
%put EFFECTIVE &=x;
%mend test;
%let line=Set earlier;
%test(x=&line);
%test(x=&&%upcase(line));
OK I now see &&%upcase(line) is the trick to hide line as a macro variable and, after resolving && to & in the call of macro test, within the macro x=&LINE is available where &LINE is not yet resolved. &&%substr(line,1) has the same effect.
Great!
Me again: the program works fine, but why? Is there a restriction when resolving parameters in a macro call, that a value is passed only once? In open code, &&%upcase(line) is resolved in a first pass to &LINE, in a second pass then to the value of the macro variable line. Is this second pass omitted when &&%upcase(line) is the value of a parameter in a macro call? I don't find any documentation on that.
2nd question: why results
%test(x=&%upcase(line));
in:
ACTUAL X=&%upcase(line)
EFFECTIVE X=&%upcase(line)
I'd think in the first pass & is kept, %upcase(line) is evaluated to LINE, together &LINE, and without 2nd pass giving the same as with 2 ampersands where in the 1st pass && is resolved to & and %upcase(line) to LINE:
ACTUAL X=&LINE
EFFECTIVE X=Set later
It is not the macro that is the issue really. The issue is that you need to get the & into the value of the macro variable (every macro parameter is a local macro variable in the macro's symbol space) without it being macro quoted so that later when the macro processor resolves the value the & will trigger the macro processor to resolve the reference. You will have similar issues trying to force an & into the value of macro variable when using the %LET statement also.
The easiest way to get un protected & and % into macro variables is to use SAS code (instead of macro code) to set the macro variable value. For example you can use CALL SYMPUTX() function in a data step or the INTO keyword in PROC SQL code. There you can use single quotes around the string to prevent the macro processor from evaluating the & reference too soon. But the single quotes are not actually part of the value like they would be in macro code.
data _null_;
call symputx('mymvar','This will resolve reference to LINE later. LINE=&line.');
run;
proc sql noprint;
select 'This will resolve reference to LINE later. LINE=&line.'
into :mymvar
from sashelp.class(obs=1)
;
quit;
All now works fine, my program does what I want it to do. But I'm still wondering why &%upcase(line) does not work but &&%upcase(line) works as posted on 04-27-2019 08:18 AM, just for my understanding.
@HWSteinberg wrote:
All now works fine, my program does what I want it to do. But I'm still wondering why &%upcase(line) does not work but &&%upcase(line) works as posted on 04-27-2019 08:18 AM, just for my understanding.
Not sure WHY it doesn't work. But HOW it doesn't work is that the value &LINE is not put into the macro variable. Instead the value &%upcase(line) is put into the macro variable.
1719 %let one=&%upcase(line); 1720 %let two=&&%upcase(line); 1721 %put one=%superq(one); one=&%upcase(line) 1722 %put two=%superq(two); two=&LINE
I suspect something about how it is breaking the string into tokens. So with one & it treats it as one token without any macro code to resolve. With two & it sees it as two tokens. The first converts to & and the stops and the second converts to LINE.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.