I'm trying to organize my SAS code by defining a macro variable called root. Then, I want to be able to have all of my %INCLUDE statements use the &root value so I can just define the %INCLUDE in terms of the root:
%LET root = C:\Documents and Settings\me\Desktop\mine\SAS;
%include "&root\lib\work.sas"
However, when trying to run this under SAS 9.2 I get the following error from the log:
1 %LET root = C:\Documents and Settings\me\Desktop\mine\SAS;
ERROR: Incorrect %INCLUDE statement will not be executed. There is a syntax error.
2 %include "&root\lib\work.sas"
So it looks likes the &root variable isn't being expanded into its value in the %INCLUDE statement. What am I doing wrong?
Thanks!
[Edit] Answer
I was missing the ';' at the end of the %INCLUDE statement. =/
In that situation you probably need to use the separator, that marks the end of a macro variable name, which is ".", so your code will look like:
%LET root = C:\Documents and Settings\me\Desktop\mine\SAS;
%include "&root.\lib\work.sas"
This is actually needed only when variable name "touches" something, but I would recommend using it ALWAYS - it's a good practise. Also when there is a dot after the variable name you should put "that" dot, so there will be two dots, like:
%LET root = C:\Documents and Settings\me\Desktop\mine\SAS;
%LET fname = work;
%include "&root.\lib\&fname..sas"
EDIT
As #Joe correctly states in other answer, the real problem in that situation is a lack of semicolon after %INCLUDE statement. Placing it after the path should solve the problem.
I have to say i'm a bit confused by your presentation of the error, plus your accepted answer. In my experience, the ERROR: Incorrect %INCLUDE statement would show up after the second line, not before. Plus, if the macro variable resolution is the issue, then the following is what you'd see:
903 %LET root = C:\temp;
904
905 %include "&roots\test.sas";
WARNING: Apparent symbolic reference ROOTS not resolved.
WARNING: Physical file does not exist, C:\Users\xxxx\&roots\test.sas.
ERROR: Cannot open %INCLUDE file &roots\test.sas.
In your included code, there is no semicolon after the %include. Is that possibly related to the problem? When I run the %include then another line that is illegal, for example running them in the opposite order, I do get that error (still after the %include, though).
I suspect you have another bug somewhere prior to this statement in your code. Try restarting SAS and executing just those two lines of code and it should work fine, it worked just fine for me:
%let root = c:\documents and settings\robert.penridge\desktop\mine\sas;
%include "&root\lib\work.sas";
EDIT: This worked for me because I actually added a semicolon. Realised this after #Joe's correct diagnosis of the problem.
I created the following folder structure on the desktop:
\mine\sas\lib
And then put work.sas in there with the following contents:
%put blah;
When I ran the code the results printed blah just fine with no error messages. In fact I have used code just like this across many versions of SAS and across many operating systems for many years. There's no issue with your code.
Contrary to what some of the other answers suggest here, SAS is smart enough to know that the \ character can not be part of a macro name so there's no need to explicitly state the end of the macro with the . character.
Finally, if you are trying to debug macro code you can also turn on the following options:
option mprint mlogic macrogen symbolgen source source2;
You can turn them back off like so:
option nomprint nomlogic nomacrogen nosymbolgen nosource nosource2;
Just be aware that some of these may already be on by default in your SAS environment.
In rare circumstances you may also be running into a macro quoting issue. This will happen if you have been using macro functions like %str() %bquote() etc... If this is the case then it can often be resolved by using the %unquote() function around the macro variable that is causing issues. From your code sample it doesn't look like this is the issue but you might have simplified your code for the post. If this were the case then in your situation the code would be changed to look like this:
%let root = c:\documents and settings\robert.penridge\desktop\mine\sas;
%include "%unquote(&root)\lib\work.sas";
Related
This appears to be an old problem but I haven't seen an answer that fully addresses it. Totally possible I just missed it.
I'm consuming data that has a text field called fullDescription that contains a string like (made up but fits the pattern):
"00001234456 Wells Fargo DR FM AT&T PYMT 00987600"
I'm attempting to parse the data and dig out tidbits like "Wells Fargo" and "AT&T". However, when I manipulate "AT&T" SAS tries to read it as "AT" then the variable value for T. It stopped erroring (but still warns) when I instituted this line:
%LET description = %SYSFUNC(COMPRESS(%BQUOTE(&&fullDescription&row),'',P));
This, at least, returns "00001234456 Wells Fargo DR FM ATT PYMT 00987600" (missing ampersand) but still throws:
WARNING: Apparent symbolic reference T not resolved
I haven't figured out a way to prevent the warning. Is there a way to leave the ampersand in but not treat it as a variable? If that's not possible, can I cleanse it once and not get the error?
You are almost there, just add %nrstr() function when define the macro variable fullDescription.
data _null_;
call symputx('fullDescription','%nrstr(00001234456 Wells Fargo DR FM AT&T PYMT 00987600)');
run;
%LET description = %SYSFUNC(COMPRESS(%bquote(&fullDescription),'',P));
%put &=description;
This makes no warning anymore.
In SAS EG there is a neat feature that allows one to see the parameters of a macro function and its definitions when typing.
For example if I execute:
%macro test
(a /* this is a */
,b /* this is b */
);
%put a b;
%mend;
And then type %test(, a popup will show me "a : this is a" etc...
Unfortunately for some reason it seems to work only IF the macro function was defined in the current program (so basically in the only place where you don't really need it, as in that case it should be quite fresh in your mind).
Is there any way to benefit from this feature in other programs and other process flows ?
More importantly, how can I benefit from this feature for my stored compiled macros ?
Say for example I defined in another session :
options mstored sasmstore=mylib;
%macro test2
(c /* this is c */
,d /* this is d */
) / store source des='show c and d';
%put c d;
%mend;
I suppose a workaround would be to create a macro %redefine_all that would go through the catalog and execute every stored macro definition, but that's quite ugly and I'm not completely sure how I'd go at it...
Sounds like a 'one of those things' thing.
The EG help "About the Program Editor" - "Using the autocomplete feature" states:
The Program Editor can also read your current program and suggest
syntax for these program elements:
macro variables that are defined by using the %LET statement or SYMPUT CALL routine
macro routines that are defined by using the %MACRO statement
data set names that are defined by using the DATA step
statement
Note: The Program Editor does not automatically list macro
variables and routines that are defined outside of the current
document (for example, external macro programs, %include files, and
autoexec files).
Long time reader first-time questioner.
Using SAS Data Integration studio, when you create a summary transformation in the table options advanced tab you can add a where statement to your code automatically. Unfortunately, it adds some code that makes this resolve incorrectly. Putting the following in the where text box:
TESTFIELD = "TESTVALUE"
creates
%let _INPUT_options = %nrquote(WHERE = %(TESTFIELD = %"TESTVALUE%"%));
In the code, used
proc tabulate data = &_INPUT (&_INPUT_options)
But resolves to
WHERE = (TESTFIELD = "TESTVALUE")
_
22
ERROR: Syntax error while parsing WHERE clause. ERROR 22-322: Syntax
error, expecting one of the following: a name, a quoted string, a
numeric constant, a datetime constant,
a missing value, (, *, +, -, :, INPUT, NOT, PUT, ^, ~.
My question is this: Is there a way to add a function to the where statement box that would allow this quotation mark to be properly added here?
Note that all functions get the preceding % when added to the where statement automatically and I have no control over that. This seems like something that should be relatively easy to fix but I haven't found a simple way yet.
The % are simply escaping the " and () characters; they're perfectly harmless, really. The bigger problem is the %NRQUOTE "quotes" (which are nonprinting characters that tell SAS this is macro-quoted); they mess up the WHERE processing.
Use %UNQUOTE( ... ) to remove these.
Example:
data have;
testfield="TESTVALUE";
output;
testfield="AMBASDF";
output;
run;
%let _INPUT_options = %nrquote(WHERE = %(TESTFIELD = %"TESTVALUE%"%));
%put &=_input_options;
data want;
set have(%unquote(&_INPUT_options.));
run;
Thank you all for your responses. Long story short, I ended up creating a SAS Troubleshooting ticket. The analyst told me that they have now documented the issue, which should now be resolved in a future iteration of DI.
The temporary solution was to create a new transformation, with a slight alteration, adding an UNQOUTE (as mentioned above by Joe) to the source code before the input options:
proc tabulate data = &_INPUT (%unquote(&_INPUT_options)) %unquote(&procOptions);
For those interested you will need to create the transformation in a public subfolder of your project so others can use it. Not what I was hoping for, but a workable solution while waiting for the version update.
I am trying to create a new variable based on the value of a macro variable. However, SAS highlights 'vari' as red, seemingly indicating that I am doing something wrong. The statement still seems to get executed correctly though. Any thoughts?
%let i=7;
data d1;
set d1;
vari&i=7;
run;
SAS syntax highlighter is an aid, but there are many situations where it is not "correct". Particularly for the macro language, it can't always guess how symbols will resolve. It doesn't have all the information (or intelligence) as the SAS word scanner/tokenizer. I use syntax highlighting as a hint that something might be wrong, but I ignore it when I've checked the code and confirmed it is correct.
The code in your example is fine.
When working is the base sas client, if a user accidentially forgets a parathesis, quote, semi-colon, or end-comment that will sometimes cause any additional code they try running to fail. If I'm trying to help someone experiencing one of these errors, how can I clear the current buffer and start fresh without opening a brand new session?
I've always used the one documented on support.sas.com
http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#a001302436.htm
*'; *"; *); */; %mend; run;
Submit that until you get the log message :
ERROR: No matching %MACRO statement for this %MEND statement.
There is no true best way, as it depends on too many things. Presumably the user will know what might have gone wrong, and can use that information; for example, are we possibly missing a %mend somewhere that caused us to get locked into a macro?
The EG method is one of the better ones. At the start of every EG process (ie, every time you hit 'Run' on a program or section of program), it runs:
;*';*";*/;quit;run;
That:
Semicolon ends any statement that hadn't ended
Comment singlequote, and comment doublequote, end any trailing quotes (both trailed by ; )
Star slash ends any block comments
Quit and run end any procedures that had been left open.
EG doesn't include %mend; because it would generate a warning, but you could include that if you didn't mind the warning and wanted to catch one of the common issues. If you do include it, put it up front - macros will not properly deal with those hanging quotes, and you need to be out of them for sure first.