SAS macro variable concatenation with text with single quotes - sas

I am using PROC SQL.
Macro variable is STUDY --- ENTERED VALUE AS CBYM
I want output like --- 'CBYM$test'
CREATE TABLE TEST AS
SELECT OWNER, VIEW_NAME
FROM SYS.ALL_VIEWS
WHERE OWNER IN ('"&STUDY"$TEST');
It is giving error. Please help me to get proper macro variable with text in single quotes in output.

First note that SAS doesn't care if you use single or double quotes for string literals. So you could just use:
"&study$TEST"
If you are passing the code directly to a remote database that does care you could try using the %BQUOTE() macro function to allow resolution of macro variable reference inside of single quotes.
%bquote('&study$TEST')
If the macro quoting causes trouble then you can use the %UNQUOTE() macro function to remove it.
%unquote(%bquote('&study$TEST'))

Related

symputx won't let me store different macro variables with the same macro function

I'm trying to write a macro function that gets attributes from a data set, and then stores them as a macro variable. I want to write this macro function in such a way that it can be used for multiple data sets, and multiple macro variables.
What's wrong with this:
%macro ExtractACell(dataset, storage_var, rownum=1, var_name=Make);
data _null_;
set &dataset. (obs=&rownum. firstobs=&rownum. keep = &var_name.);
call symputx(&storage_var., &var_name., "G");
stop;
run;
%mend ExtractACell;
Whenever I try to run that I get notes like this:
NOTE: The quoted string currently being processed has become more than 262 bytes long. You might have unbalanced quotation marks.
NOTE: The quoted string currently being processed has become more than 262 bytes long. You might have unbalanced quotation marks.
27 %let SASWORKLOCATION="%sysfunc(getoption(work))/";
Does symputx have rules against passing in macro variables that represent names of macro variables?
Make sure you are generating valid SAS code when your macro variables are expanded. In particular this statement:
call symputx(&storage_var., &var_name., "G");
Would require you to call the macro with quotes around the name of the macro variable you want it to create. Like this:
%ExtractACell(dataset=sashelp.cars, storage_var="mymvar", rownum=1, var_name=Make);
It might be simpler to code the macro using this statement.
call symputx("&storage_var", &var_name., "G");
Then you could call without the quotes around the macro variable name:
%ExtractACell(dataset=sashelp.cars, storage_var=mymvar, rownum=1, var_name=Make);
PS Your whole process is probably messed up if you need that macro.

Find current value of ODS ESCAPECHAR

I am writing a macro to help create documentation which must use ods escapechar. I need it to preserve whatever options/setting the original program used. However, setting a new escape character in the macro overwrites the original program's escape character. How can I change the escape character only for the duration of my macro?
Is there a table somewhere in SAS which stores the current ods escapechar? My thought is to assign the current value to a macro variable and use that to reassign it once my process is complete.
Use the escape sequence instead
(*ESC*)
Then you don't have to know or reset anything.
Somewhere around 9.3 (?) they added &SYSODSescapeChar:
%put &=SYSODSescapeChar ;
SYSODSESCAPECHAR=^
But since the generic (*ESC*) mentioned by data_null_ came first, I'm in the habit of using that, rather than do the save option / reset option / restore saved option dance.

SAS ODS escape character macro variable error

The SAS v9.4 documentation lists an automatic macro variable &sysodsescapechar which contains the current ODS escape character, assigned using ods escapechar=.
Whenever I try to view the macro variable using a %put statement, I get the following error:
ERROR: Open code statement recursion detected.
This happens when open code erroneously causes a macro statement to call another macro statement.
I've tried all of the following:
%put &=sysodsescapechar.;
%put %nrbquote(&sysodsescapechar.);
%put %superq(sysodsescapechar);
They all result in the same error.
When I try to view the macro variable using a data step, it appears to be empty.
data test;
esc = "&sysodsescapechar.";
put esc=;
run;
If the macro variable actually is empty, why do I get open code statement recursion errors? The %put statement on its own is valid, so putting an empty variable shouldn't be an issue.
Any guidance here would be much appreciated.
What's happening is the escape char seems to need a close parentheses. For example:
%put %superq(SYSODSESCAPECHAR););
;
It escapes the ) , which means now you have
%put superq(;);
In your first example, it's a little trickier because a semicolon by itself doesn't seem to be escaped so you have to provide a close parentheses:
%put &SYSODSESCAPECHAR.)x;
x
That works, for example. I'm not sure if it's only close paren or other things that would also allow it to stop trying to escape, but that's the only thing I can tell works.
You can look at the actual value of the macro variable in SASHELP.VMACRO; it's not ' ' (which is indeed what gets passed to the data step even with SYMGET, but it's clearly parsed). In that table it is '03'x, which looks like a uppercase L in the upper half of the character. That is the "End of Text" control character. I suspect the behavior in the editor when using this in text (in a macro variable) is simply a behavior of the editor - '03'x is not representable on many editors (if I try to paste it here, for example, it isn't displayed, but does exist as something I can backspace over with zero width). SAS is clearly capable of dealing with a 'normal' ods escapechar but isn't capable of dealing with '03'x in the same fashion.

How to mask potential macro variables as part of a filename URL string

I have written the following filename statement as part of a program to dynamically pull down stock quotes in iterative steps. This now works fine, except for three warning messages I am getting in the log:
1) &s= is not resolved
2) &f= is not resolved
3) Warnings: String is more than 252 characters long, you may have unbalanced quotations
filename loader url "http://finance.yahoo.com/d/quotes.csv?s=&svar1.+&svar2.+&svar3.+&svar4.+&svar5.+&svar6.+&svar7.+&svar8.+&svar9.+&svar10.+
&svar11.+&svar12.+&svar13.+&svar14.+&svar15.+&svar16.+&svar17.+&svar18.+&svar19.+&svar20.+
&svar21.+&svar22.+&svar23.+&svar24.+&svar25.+&svar26.+&svar27.+&svar28.+&svar29.+&svar30.+
&svar31.+&svar32.+&svar33.+&svar34.+&svar35.+&svar36.+&svar37.+&svar38.+&svar39.+&svar40.+
&svar41.+&svar42.+&svar43.+&svar44.+&svar45.+&svar46.+&svar47.+&svar48.+&svar49.+&svar50.+
&svar51.+&svar52.+&svar53.+&svar54.+&svar55.+&svar56.+&svar57.+&svar58.+&svar59.+&svar60.+
&svar61.+&svar62.+&svar63.+&svar64.+&svar65.+&svar66.+&svar67.+&svar68.+&svar69.+&svar70.+
&svar71.+&svar72.+&svar73.+&svar74.+&svar75.+&svar76.+&svar77.+&svar78.+&svar79.+&svar80.+
&svar81.+&svar82.+&svar83.+&svar84.+&svar85.+&svar86.+&svar87.+&svar88.+&svar89.+&svar90.+
&svar91.+&svar92.+&svar93.+&svar94.+&svar95.+&svar96.+&svar97.+&svar98.+&svar99.+&svar100.+
&svar101.+&svar102.+&svar103.+&svar104.+&svar105.+&svar106.+&svar107.+&svar108.+&svar109.+&svar110.+
&svar111.+&svar112.+&svar113.+&svar114.+&svar115.+&svar116.+&svar117.+&svar118.+&svar119.+&svar120.+
&svar121.+&svar122.+&svar123.+&svar124.+&svar125.+&svar126.+&svar127.+&svar128.+&svar129.+&svar130.+
&svar131.+&svar132.+&svar133.+&svar134.+&svar135.+&svar136.+&svar137.+&svar138.+&svar139.+&svar140.+
&svar141.+&svar142.+&svar143.+&svar144.+&svar145.+&svar146.+&svar147.+&svar148.+&svar149.+&svar150.+
&svar151.+&svar152.+&svar153.+&svar154.+&svar155.+&svar156.+&svar157.+&svar158.+&svar159.+&svar160.+
&svar161.+&svar162.+&svar163.+&svar164.+&svar165.+&svar166.+&svar167.+&svar168.+&svar169.+&svar170.+
&svar171.+&svar172.+&svar173.+&svar174.+&svar175.+&svar176.+&svar177.+&svar178.+&svar179.+&svar180.+
&svar181.+&svar182.+&svar183.+&svar184.+&svar185.+&svar186.+&svar187.+&svar188.+&svar189.+&svar190.+
&svar191.+&svar192.+&svar193.+&svar194.+&svar195.+&svar196.+&svar197.+&svar198.+&svar199.+&svar200.
&f=&&fvar&a.";
Firstly, how can I mask the &s= &f= from the processor, but allow it still resolve the &svar macro variables? I have tried various attempts at using %superq and %nrbquote but not had much luck.
Also, is there a way to a mask the warning about the string being long other than using log errors to suppress all options? Ideally I don't want to do that as I would still like to see any new errors that may arise for whatever reason.
Thanks
To turn off the warning about string being too long, use system option NOQUOTELENMAX.
To mask an & that you can see, try %NRSTR(), e.g. %NRSTR(&f).
To "mask" the ampersand so it is not scanned by the macro processor, just use the %STR function. I don't see any reference to an &s variable in the code you show, but I do see one from&f. Change that last parameter to:
%str(&)f=&&fvar&a.
Also, to assist debugging things like this, I strongly suggest that you build the entire string into it's own macro variable (perhaps named url). In other words:
%let url="http://finance.yahoo.com/d/quotes.csv?%str(&)s=//svars// %str(&)f=&&fvar&a.";
%put url=&url;
filename loader url "&url";
I'm guessing that the s= was &s= in the code that had the error and I substituted your long parameter string with //svars// only to save formatting in this answer.
Using a "helper macro variable" like this should help during development. The %put just echos the string during testing and would not be part of the final macro.

Unmatched quotation mark issue in SAS

As is known to all, SAS needs special care to quotation marks inside a sentence.
E.g.
%let quoted="I'd like to";
data temp;
set temp;
quoted="&quoted";
run;
error is encounterred when submitting.
In fact I need to copy data to one dataset from another one, in which there are a lot of records containing quotation marks. When assigning, error occurrs and data step stop executing, causing rest of the code to be invalid. So in this case, it's impossible to modify original data set by adding duplicated quotation marks, which doesn't make sense.
So instead of having to add a duplicated one, like, "I''d like to", is there any other way of avoiding the error, or making data step keeping executing?
Thanks,
When using the macro language (including the %let command) you do not want to use quotes to identify text strings. To place a single quote in a string you must use one of the macro utility masking functions such as %str(). The correct syntax to place a single unmatched quote in a macro variable using %let is shown below. The % symbol before the single quote is an escape character to tell SAS that the following character (a single quote) should be used as a literal. Also note that I've removed the double quotes from the %let as they are not required.
%let quoted=%str(I%'d like to);
data temp;
quoted="&quoted";
run;
Cheers
Rob
I'm not sure what you're trying to achieve in the actual situation, but in the above situation it can be solved removing the double quotation marks in the data step.
%let quoted="I'd like to";
data temp;
set temp;
quoted=&quoted;
run;