Hi All,
Short question: Why does the open() function apparently unquote macro variables.
For example:
340 %put %sysfunc(open (in(where=(var="%nrstr(%Something)"))));
WARNING: Apparent invocation of macro SOMETHING not resolved.
0
The user has quoted the value because %Something is a text string, not a macro invocation, but the open function is unmasking it, producing the warning message. (The result is still fine).
Compare the above result to the length() function, which does NOT unmask the value (expected behavior).
341 %put %sysfunc(length(in(where=(var="%nrstr(%Something)"))));
28
In this simple case of course user could change the code to use single quotes to hide the percent sign:
%put %sysfunc(open(in(where=(var='%Something')));
But wondering if people agree that it is odd that open() is unquoting, and if there is a way to prevent this. It feels like a bug to me, does it to you?
Longer version/background:
This came up because an autocall library had a %nobs macro, something like:
%macro nobs(data); /*macro function in autocall library to return # obs in a dataset*/
%local nobs dsid rc;
%let dsid=%sysfunc(open(&data));
%let nobs=%sysfunc(attrn(&dsid,NLOBSF));
%let rc=%sysfunc(close(&dsid));
&nobs
%mend nobs;
User wrote a macro like:
%macro report(data=,type=);
%if %nobs(&data(where=(type="&type")))=0 %then %do;
data _null_;
file print;
put "There were no records in &data with type=&type";
run;
%end;
%else %do;
title1 "Printout of &data where Type=&Type";
proc print data=&data;
where type="&type";
run;
title1;
%end;
%mend report;
And got the warning message when they ran:
data test;
input Year Type $14. Value;
cards;
2001 AbsoluteChange 10
2002 AbsoluteChange 20
2003 AbsoluteChange 30
2001 %Change 5
2002 %Change 10
2003 %Change 15
;
run;
%report(data=test,type=%nrstr(%Change))
So the user deduces that it is %nobs which is unmasking the percent sign in %Change, and calls the guy who maintains the autocall library and asks him to fix it. But I don't see how %nobs can be fixed to avoid this problem. Given the number of %nobs (and other) macro functions that are floating around autocall libraries that use the open function, was wondering if anyone had a good fix. If not, I guess I'm stuck adding a limitation to every macro that uses the open() function to say that it will unquote values, and telling the user to redesign %report.
Thanks,
--Quentin
You can change your report code to use SYMGET in the argument constructed for the data parameter to nobs. This will alleviate issues related to passing seemingly unmaskable characters in the chain of calls.
%macro report(data=, type=);
%if %nobs(&data(where=(type=symget('type'))))=0 %then %do;
...
The autocall maintainer of NOBS() should SUPERQ the data parameter to avoid unwanted interpretations.
%let dsid=%sysfunc(open(%superq(data)));
Holy Necrothread Revival Batman! The question was posed 10 years ago.
Maybe even longer... this feels like a question from a job I was at more than 10 years ago. But it's possible I was writing about myself as the user, in which case maybe 10 years is believable...
See more recent discussion about the impact of macro quoting on arguments passed to %SYSFUNC().
If I remember the logic right it basically required double quoting. Something like.
%nrstr(%nrstr(%something))
Don't miss out on SAS Innovate - Register now for the FREE Livestream!
Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.
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.