Macro programming is generally 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 and the next article explains how you can create SAS macro variables.
Using these techniques you can create an 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 to greatly 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 then the Proc step will be compiled and executed whereas macros are resolved and compiled prior to 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 basic 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 by 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 useful as it has the ability to pass parameters much 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. In a keyword parameter, you can apply a default value. In the above example of the keyword parameter, the default variable ‘age’ has been given. If the macro is called without specifying any parameter, the default variable will be taken as ‘age’.
Passing Multiple Parameters
Mostly, a combination of positional and keyword parameters are used. However, positional parameters must come before keyword parameters.
Working with Macro Strings
Macros and macro variables can only be assigned string of text. String functions on macro variables are handled implicitly:
Quotes are not necessary around the values of a macro variable. 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="https://b-cdn.net/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="https://b-cdn.net/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='https://b-cdn.net/folders/myfolders/&filename..xls' out=customers
replace;
run;
This does not work.
proc import datafile="https://b-cdn.net/folders/myfolders/&filename..xls" out=customers
replace;
run;
This will work as macro variable &filename is inside a double quote.
Evaluating Numeric Strings
Since SAS macro variables are strings and not numerical values, the below expression will not work.
%let sum = 1+1;
%put ∑
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.
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 = 1 - odd
i = 2 - even
i = 3 - odd
i = 4 - even
i = 5 - odd
i = 6 - even
i = 7 - odd
i = 8 - even
i = 9 - odd
Control statements in macro are not valid in open code. They must be contained within macros.
SYMPUT and SYMGET
Macros are resolved prior to 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;
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.
Hence, the above code has to be replaced with:
data newClass;
set sashelp.class;
call symput('age',age**2);
run;
%put &age;
225
Using Symget:
data class;
set newClass;
age2=&age;
age3=symget('age');
run;
SYMGET
returns a character value that is 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 of the program issues a message for an invalid argument to a function.
Debugging SAS macros
Debugging a macro code isn’t an easy process. By seeing the ERROR messages in LOG it is difficult to identify the problem. Hence, with the use of the below system option, you will be able to debug macros easily.
1. MPRINT
MPRINT
translates the macro language to regular SAS language and writes to the SAS log for each SAS statement.
2. 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.
3. 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 the 3 systems options have enabled which shows 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
For detailed information on troubleshooting steps in macros, you can refer to the SAS V8 documentation website.