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).
Related
I have a dataset with a variable called pt with observations 8.1,8.2,8.3 etc and a variable called mean with values like 8.24 8.1 8.234 etc. Which are paired with each other.
I want to be able to set my put informat to the formats from the variable num.
I get the errors "Expecting an arithmetic expression"
"the symbol is not recognized and will be ignored" and "syntax error" from my code. (underlining the &fmt. part)
if pt=&type;
call symput("fmt",pt);
fmt_mean = putn(mean,&fmt.);
Thanks in advance for your help.
The macro processor's work is done before SAS compiles and runs the data step. So trying to place the value into a macro variable and then use it immediately to generate and execute SAS code will not work.
But since you are using the PUTN() function it can use the value of an actual variable, so there is no need to put the format into a macro variable.
fmt_mean = putn(mean,pt);
Please, post your data set and data step. Your description is hard to understand.
However the solution seems to be simple: do not use macro variables! You don't need them here. Unlike put() function which expect format know at compile time (that is when you can use macro variables) its analog putn() expects second argument to be variable. Of course, it works a little slower due to that permittance. So your code can look like that:
data ...;
set ...(keep=mean pt);
fmt_mean = putn(mean, pt);
run;
where pt variable maybe numeric, i.e. 8.2, or character, i.e. '8.2'.
If you want to understand how SAS macro works and what call symput does look here:
https://stackoverflow.com/a/69979074/7864377
I have some problem to find out if what I want to do is possible or not on SAS EG 7.15.
Context
We have splitted a quite big project into several flow process which have each one a program to define a %macro statement and a final process flow which contain a program call "EXECUTION" to call all those program in the row in this way :
Flow_Process_1/program:
%macro TheFirstOne;
some code
%mend TheFirstOne;
some other process flow
Flow_Process_123/EXECUTION:
%TheFirstOne;
%TheSecondOne;
%TheThirdOne;...
The advantage is that all is splitted and easy to execute just by a click on the first process flow -> SHIFT+Click on the last one and everything is going to be executed. Also you have a unique log file of all the different program in one. And everything works perfectly.
The Problem
The problem is that we have a quite long execution (in time) that we wanted to split into parallel process which is not really hard to set with the "Allow Parallel execution on the same server" option and this feature also work like a charm when you try to execute some program which work on their own.
However, with the way we are working, the first process (thread i would say) knows about our %macro definition and works perfectly, but the second or any other one don't know about them and give error like :
WARNING: Apparent invocation of macro xxxxxxx not resolved.
since we never execute the program before which define this macro before.
My attempt
I tried to use the Autoexec feature but I have to copy the definition of every macro (5000 + lines) inside if that it works for every parallel process. I also looked into SAS code to run a flow process in a program but it looks like it does not exist, or I did not find it.
I'm quite sure that senior in SAS will say that is not the way we should use SAS EG, but we did that way and I just would like to know if there is a solution to let know to other process the definition of all %macro define previously.
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.
This might be a rather simple question but I am new to SAS and am clueless even after researching on this in Google.
I have a macro variable as -
%let list = 12AUG2013 13AUG2013 15AUG2013 16AUG2014 09SEPT2014;
I need to get the following things -
a) Total words in list: In R this would be length(list). But in SAS, length counts each character. COUNTW does not work. Anyway I can do this?
b) Finding the ith word: If I need the 3rd element in this list, I would say list[3] in R. How can I do that in SAS?
c) Finding the position of an element: Suppose I need to know which position 16AUG2014 is at in the list variable, how can I get it?
Thanks for all the help!
As you're asking about macro variables, it's a little different to using SAS data-step functions. Your questions provide a useful example of how they differ. Some data-step functions have macro function equivalents %SCAN, %SUBSTR etc. Others will require the use of %SYSFUNC, which allows most SAS datastep functions to be converted into macro functions.
So, referring to your example:
%let list = 12AUG2013 13AUG2013 15AUG2013 16AUG2014 09SEPT2014;
%let list_numwords = %sysfunc(countw(&list)); /* This example shows the use of SYSFUNC */
%let list_word3 = %scan(&list,3); /* These examples show the use of SCAN and INDEX, inbuilt macro functions*/
%let list_pos16AUG2014 = %index(&list,16AUG2014);
The code creates new macro variables that store the answers to your questions a,b and c* respectively.
* If you require the word number of 16AUG2014 (i.e. 4), then this is a little more difficult as I don't think there's a string function for this in SAS. It would involve using a combination of COUNT and %SUBSTR.
The Code for position in list is
%let list_pos=%sysfunc(countw(%substr(&list,1,%index(&list,16AUG2014)+1)));
Cheers
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";