Macro programming is considered to be an advanced topic in SAS. Though macros can be challenging, it is also true that the basic concepts are not difficult to learn.
Assuming you know the basics of SAS Programming, In this tutorial, you will learn how the macro processor works and how to use SAS macros. The following article explains how you can create SAS macro variables.
Using these techniques, you can create efficient and reusable code that can save you time and effort.
Why use SAS macros?
Macros can automatically generate SAS codes and allow you to make more dynamic and generalized SAS programs. Macros can help significantly reduce the effort required to read or write repetitive SAS codes.
SAS program compilations
SAS codes are compiled and executed alternatively in steps. First, A data step will be compiled and executed, and then the Proc step will be compiled and executed, whereas macros are resolved and compiled before the compilation of SAS code.
In a standard SAS program, SAS compiles and then immediately executes it. Whereas in macro code, there is an extra step.
SAS passes your macro statements to the macro processor, which then “resolves” your macros generating standard SAS code. Then, SAS can compile and execute the program.
The two essential elements of macro code are SAS macro variables and SAS macros.
Macro variables hold the value as a text string. The easiest way to assign a value to a macro variable is using the %let statement.
UPCASE(character-value)%let macro_var = Hello;
%put The value of macro_var is &mac_var;
In the above example, ¯o_var refers to a macro variable and %macro_var refers to a macro.
SAS Macro Parameters
SAS Macros are more beneficial as they can pass parameters like any functions in other languages.
For example, for calculating means, we often vary the set of variables without changing the rest of the code:
%macro means (var);
proc sort data=sashelp.class out=class;
by &var;
run;
proc means data=class;
by &var;
run;
%mend;
%means(age);
Positional vs Keyword Parameters
You can specify macro parameters in two ways.
Positional Parameters
%macro means (var);
proc sort data=sashelp.class out=class;
by &var;
run;
proc means data=class;
by &var;
run;
%mend;
%means(age height);
Keyword Parameters
%macro means (var=age);
proc sort data=sashelp.class out=class;
by &var;
run;
proc means data=class;
by &var;
run;
%mend;
%means(var=height);
Each of the above ways has its advantages. For example, you can apply a default value in a keyword parameter.
The default variable ‘age’ has been given in the above example of the keyword parameter.
The default variable will be considered ‘age’ if the macro is called without specifying any parameter.
Passing Multiple Parameters
A combination of positional and keyword parameters is primarily used; however, positional parameters must come before keyword parameters.
Working with Macro Strings
Macros and macro variables can only be assigned strings of text. String functions on macro variables are handled implicitly:
Quotes are not necessary around the values of a macro variable. However, a period(.) is a signal in SAS to end a macro variable name if the requirement is to import data from a file called “customer_details.xls”, which is assigned in a macro variable filename.
The below code doesn’t work.
%let filename=customer_details;
proc import datafile="/folders/myfolders/&filename.xls" out=customers
replace;
run;
We need to replace the &filename.xls with &filename..xls.
%let filename=customer_details;
proc import datafile="/folders/myfolders/&filename..xls" out=customers
replace;
run;
Double vs Single Quotes in SAS Macros
Double quotes and single quotes affect SAS macro variables differently, and macro variables inside a single quote are not resolved.
proc import datafile='/folders/myfolders/&filename..xls'
out=customers replace;
run;
This does not work.
proc import datafile="/folders/myfolders/&filename..xls"
out=customers replace;
run;
This will work as a macro variable &filename is inside a double quote.
[Recomended Reading: SAS macro parameters with commas]
Evaluating Numeric Strings
Since SAS macro variables are strings and not numerical values, the below expression will not work.
%let sum = 1+1;
%put sum
1+1
The function %eval is used to obtain the integer or numeric value of an expression containing SAS macro variables.
%let total = %eval(&sum);
%put &total;
2
Floating-point evaluations can be performed with %sysevalf.
Read: ̣Exploring SAS Macro functions – eval and sysevalf
Conditional Statements
In SAS Macros, we can apply conditional statements using %IF %THEN, %DO,%WHILE, and %DO % UNTIl like below –
%macro OddEven();
%do i=1 %to 9;
%if %sysfunc(mod(&i, 2))=0 %then
%put i = &i - even;
%else
%put i = &i - odd;
%end;
%mend;
%OddEven();
Output:
i <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator">-</span> odd i <span class="token operator">=</span> <span class="token number">2</span> <span class="token operator">-</span> even i <span class="token operator">=</span> <span class="token number">3</span> <span class="token operator">-</span> odd i <span class="token operator">=</span> <span class="token number">4</span> <span class="token operator">-</span> even i <span class="token operator">=</span> <span class="token number">5</span> <span class="token operator">-</span> odd i <span class="token operator">=</span> <span class="token number">6</span> <span class="token operator">-</span> even i <span class="token operator">=</span> <span class="token number">7</span> <span class="token operator">-</span> odd i <span class="token operator">=</span> <span class="token number">8</span> <span class="token operator">-</span> even i <span class="token operator">=</span> <span class="token number">9</span> <span class="token operator">-</span> odd
Control statements in macro are not valid in open code. They must be contained within macros.
SYMPUT and SYMGET
Macros are resolved before the execution of the data step. There are special routines required for macros to communicate with the data.
- SYMPUT puts data into a macro.
- SYMGET extracts data from a macro.
data newClass;
set sashelp.class;
%let Age = Age**2;
run;
%put &age;
Output:
Age**2
In the above example, the value in age macro is set to Age**2 as the macro statement was resolved before the data step.
data newClass;
set sashelp.class;
call symput('age',age**2);
run;
%put &age;
Output:
225
Using Symget:
data class;
set newClass;
age2=&age;
age3=symget('age');
run;
SYMGET returns a character value of the maximum length of a DATA step character variable. Any value that is longer is truncated.
SYMGET returns a missing value if it cannot locate the macro variable identified as the argument; as a result, the program issues a message for an invalid argument to a function.
Debugging SAS macros
Debugging a macro code isn’t an easy process. It is difficult to identify the problem by seeing the ERROR messages. Hence, using the below system option, you can debug macros easily.
- MPRINT
MPRINT translates the macro language to regular SAS language and writes to the SAS log for each SAS statement.
- MLOGIC
MLOGIC marks the beginning of macro execution. It shows the values resolved at macro invocation. Additionally, it shows a %IF condition is TRUE or FALSE.
- SYMBOLGEN
The SYMBOLGEN system option writes the results of resolving macro to the SAS log for easy debugging.
options mlogic symbolgen mprintnest;
%macro OddEven();
%do i=1 %to 9;
%if %sysfunc(mod(&i, 2))=0 %then
%put i = &i - even;
%else
%put i = &i - odd;
%end;
%mend;
%OddEven();
In the above example, all three systems options have been enabled, showing detailed information about the macro in the SAS log.
MLOGIC(ODDEVEN): Beginning execution.
MLOGIC(ODDEVEN): %DO loop beginning; index variable I; start value is 1; stop value is 9; by value is 1.
SYMBOLGEN: Macro variable I resolves to 1
MLOGIC(ODDEVEN): %IF condition %sysfunc(mod(&i, 2))=0 is FALSE
MLOGIC(ODDEVEN): %PUT i = &i - odd
SYMBOLGEN: Macro variable I resolves to 1
You can refer to the SAS V8 documentation website for detailed information on troubleshooting steps in macros.