Lesson 11, Part 1: Macros with Positional vs. Keyword Parameters¶
"Macro variables are useful for simple text substitution. They cannot perform conditional operations, DO loops, and other more complex tasks. For this type of work, you must define a macro". (SAS Documentation)
Macro with positional parameters - Example 1¶
In the code snippet below, the %MACRO statement includes two positional parameters, dsn and howmany. The generated SAS code prints the specified dataset when the macro is called or invoked.
An important note:
- The order of the parameters in the macro call is critical.
ods html close;
options nonumber nocenter nodate symbolgen;
%macro modular (dsn, howmany);
title "sashelp.&dsn";
proc print data=sashelp.&dsn(obs=&howmany) noobs;
run;
%mend modular;
%modular(class, 2)
%modular(iris, 3)
%modular(retail,5)
| Name | Sex | Age | Height | Weight |
|---|---|---|---|---|
| Alfred | M | 14 | 69.0 | 112.5 |
| Alice | F | 13 | 56.5 | 84.0 |
| Species | SepalLength | SepalWidth | PetalLength | PetalWidth |
|---|---|---|---|---|
| Setosa | 50 | 33 | 14 | 2 |
| Setosa | 46 | 34 | 14 | 3 |
| Setosa | 46 | 36 | 10 | 2 |
| SALES | DATE | YEAR | MONTH | DAY |
|---|---|---|---|---|
| $220 | 80Q1 | 1980 | 1 | 1 |
| $257 | 80Q2 | 1980 | 4 | 1 |
| $258 | 80Q3 | 1980 | 7 | 1 |
| $295 | 80Q4 | 1980 | 10 | 1 |
| $247 | 81Q1 | 1981 | 1 | 1 |
Macro with keyword or named parameters - Example 2¶
In the code snippet below, the %MACRO statement includes two keyword parameters using the equal sign. The generated SAS code prints the specified number of observations from the dataset specified when the macro is called or invoked.
Advantages of using keyword parameters:
- You may give default values to the parameters in the macro call.
- You may list the parameters in any order in the macro call.
- Parameters get default values if you do not specify them.
%MACRO printdata(dsn, num=);
PROC PRINT DATA=&dsn (obs=&num) noobs;
%put _local_;
RUN;
%MEND printdata;
%printdata(SASHELP.CLASS, num=3)
%printdata(num=4, SASHELP.IRIS)
%printdata(SASHELP.CLASSFIT, num=2)
SAS Connection established. Subprocess id is 15424
| Name | Sex | Age | Height | Weight |
|---|---|---|---|---|
| Alfred | M | 14 | 69.0 | 112.5 |
| Alice | F | 13 | 56.5 | 84.0 |
| Barbara | F | 13 | 65.3 | 98.0 |
| Species | SepalLength | SepalWidth | PetalLength | PetalWidth |
|---|---|---|---|---|
| Setosa | 50 | 33 | 14 | 2 |
| Setosa | 46 | 34 | 14 | 3 |
| Setosa | 46 | 36 | 10 | 2 |
| Setosa | 51 | 33 | 17 | 5 |
| Name | Sex | Age | Height | Weight | predict | lowermean | uppermean | lower | upper |
|---|---|---|---|---|---|---|---|---|---|
| Joyce | F | 11 | 51.3 | 50.5 | 56.9933 | 43.8044 | 70.1823 | 29.8835 | 84.103 |
| Louise | F | 12 | 56.3 | 77.0 | 76.4885 | 67.9601 | 85.0169 | 51.3145 | 101.662 |
In the following example, the default value is assigned to the macro parameter.
*Ex13_macro.sas;
*Contributed to SAS-L by Ron RJF Fehd - 8/17/2017 and Adapted here;
options obs=max nodate nonumber nosource symbolgen;
ods html close;
%macro means(data = sashelp.class
,var = height
,where = 1);
proc means data = &data
(where =(&where));
var &var;
title "&data &var &where";
run;
%mend means;
%means()
%means(where=sex eq 'F')
%means(where=sex eq 'M')
%means(var=weight)
%means(var=weight,where=sex eq 'F')
%means(var=weight,where=sex eq 'M')
%means(data=sashelp.shoes,var=sales)
The MEANS Procedure
| Analysis Variable : Height | ||||
|---|---|---|---|---|
| N | Mean | Std Dev | Minimum | Maximum |
| 19 | 62.3368421 | 5.1270752 | 51.3000000 | 72.0000000 |
The MEANS Procedure
| Analysis Variable : Height | ||||
|---|---|---|---|---|
| N | Mean | Std Dev | Minimum | Maximum |
| 9 | 60.5888889 | 5.0183275 | 51.3000000 | 66.5000000 |
The MEANS Procedure
| Analysis Variable : Height | ||||
|---|---|---|---|---|
| N | Mean | Std Dev | Minimum | Maximum |
| 10 | 63.9100000 | 4.9379370 | 57.3000000 | 72.0000000 |
The MEANS Procedure
| Analysis Variable : Weight | ||||
|---|---|---|---|---|
| N | Mean | Std Dev | Minimum | Maximum |
| 19 | 100.0263158 | 22.7739335 | 50.5000000 | 150.0000000 |
The MEANS Procedure
| Analysis Variable : Weight | ||||
|---|---|---|---|---|
| N | Mean | Std Dev | Minimum | Maximum |
| 9 | 90.1111111 | 19.3839137 | 50.5000000 | 112.5000000 |
The MEANS Procedure
| Analysis Variable : Weight | ||||
|---|---|---|---|---|
| N | Mean | Std Dev | Minimum | Maximum |
| 10 | 108.9500000 | 22.7271864 | 83.0000000 | 150.0000000 |
The MEANS Procedure
| Analysis Variable : Sales Total Sales | ||||
|---|---|---|---|---|
| N | Mean | Std Dev | Minimum | Maximum |
| 395 | 85700.17 | 129107.23 | 325.0000000 | 1298717.00 |
PARMBUFF option in the macro definition¶
There may be a stuation when you want to write a macro containing a variable number of parameters. Use the PARMBUFF option with the macro name.
With this option in the macro definition, the list of values specified in the macro call is passed into the automatic macro variable SYSPBUFF.
Notice that the resolved value of the macro variable reference &SYSPBUFF also includes the () and the commas.
&SYSBUFF is found in the symbol table that is local to the executing macro.
options nocenter nonumber nodate nonotes nosource;
ods html close;
%macro mymacro/PARMBUFF;
%put varlist: &=SYSPBUFF;
%put Parentheses and commas deleted: %sysfunc(translate(&syspbuff,%str( ), (,) ));
%mend mymacro;
%mymacro (age, sex, weight, height)
The SAS System
varlist: SYSPBUFF=(age, sex, weight, height)
Parentheses and commas deleted: age sex weight height
E3969440A681A2408885998500000008
* Macro with a positional parameter - %sysfunc (Source: SAS Documentation);
proc format;
value category
Low-<0 = 'Less Than Zero'
0 = 'Equal To Zero'
0<-high = 'Greater Than Zero'
other = 'Missing';
run;
%macro try(parm);
%put &parm is %sysfunc(putn(&parm,category.));
%mend;
%try(1.02)
%try(.)
%try(-.38)
The SAS System
1.02 is Greater Than Zero
. is Missing
-.38 is Less Than Zero
E3969440A681A2408885998500000009
Macro with automatic macro variables¶
Authored by SAS(R) Instutute - Received from SAS Technical Support
*Ex12_GetInfo_Host_Computer;
*Authored by SAS(R) Instutute - Received from SAS Technical Support;
options nonotes nodate nonumber nosource nosymbolgen;
ods html close;
%macro getInfo;
options nosyntaxcheck ;
LIBNAME _ALL_ LIST;
%put Site Number: &syssite ;
%put Host OS: &sysscp; %put &sysscpl;
%put Hostname: &systcpiphostname ;
%put Process: &sysprocessname ;
%put SAS Version: &sysvlong ;
%let sasroot=%sysget(SASROOT) ;
%put SASROOT: &sasroot ;
%put USER: &sysuserid ;
%put Bitness: &SYSADDRBITS ;
%put Username: %SYSGET(USERNAME) ;
%put Random: %SYSGET(SAS_NO_RANDOM_ACCESS) ;
%put This job started on &sysdate at &systime;
%mend ;
%getInfo
The SAS System
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: _TOMODS1
Site Number: 70158136
Host OS: WIN
X64_10PRO
Hostname: CCASTA-HWJP0G2
Process: Object Server
SAS Version: 9.04.01M7P080520
SASROOT: C:\Program Files\SASHome\SASFoundation\9.4
USER: muhuri
Bitness: 64
Username: muhuri
Random: 1
This job started on 03APR26 at 14:32
The SAS System
E3969440A681A2408885998500000011
* Capture the conditional logic in the macro;
options nocenter nodate nonumber nosource;
ods html close;
%macro checkds(dsn);
%if %sysfunc(exist(&dsn)) %then
%do;
proc print data=&dsn (obs=5);
run;
%end;
%else
%do;
%put The data set &dsn does not exist.;
%end;
%mend checkds;
%checkds(sashelp.class)
Starting with the SAS 9.4M5 release, you can remove the %MACRO/%MEND wrapper and the macro call. See the code below.
options nocenter nodate nonumber nosource;
ods html close;
%if %sysfunc(exist(SASHELP.CLASS)) %then
%do;
proc print data=SASHELP.CLASS (obs=5);
run;
%end;
%else
%do;
%put The data set SASHELP.CLASS does not exist.;
%end;
| Obs | Name | Sex | Age | Height | Weight |
|---|---|---|---|---|---|
| 1 | Alfred | M | 14 | 69.0 | 112.5 |
| 2 | Alice | F | 13 | 56.5 | 84.0 |
| 3 | Barbara | F | 13 | 65.3 | 98.0 |
| 4 | Carol | F | 14 | 62.8 | 102.5 |
| 5 | Henry | M | 14 | 63.5 | 102.5 |
Below are two macros with no parameters.
options nonotes nodate nonumber nosource;
ods html close;
%macro getInfo;
options nosyntaxcheck ;
%put Site Number: &syssite ;
%put Host OS: &sysscp; %put &sysscpl;
%put SAS Version: &sysvlong ;
%put USER: &sysuserid ;
%put Username: %SYSGET(USERNAME) ;
%put Random: %SYSGET(SAS_NO_RANDOM_ACCESS) ;
%put This job started on &sysdate at &systime;
%mend getinfo ;
%getInfo
The SAS System
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: _TOMODS1
Site Number: 70158136
Host OS: WIN
X64_10PRO
SAS Version: 9.04.01M7P080520
USER: muhuri
Username: muhuri
Random: 1
This job started on 23MAR25 at 23:05
The SAS System
E3969440A681A2408885998500000005
options nosource nodate nonumber;
%let course=STAT 4197;
%macro mymacro;
%let course=STAT 6197;
%put The value of the macro variable inside MYMACRO is &course;
%put _user_;
%mend mymacro;
%mymacro
%put The value of macro variable course outside MYMACRO is &course;
The SAS System
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: _TOMODS1
The value of the macro variable inside MYMACRO is STAT 6197
GLOBAL COURSE STAT 6197
The value of macro variable course outside MYMACRO is STAT 6197
E3969440A681A2408885998500000007
options nosource nodate nonumber;
%let course=STAT 4197;
%macro mymacro;
%local course;
%let course=STAT 6197;
%put The value of the macro variable inside MYMACRO is &course;
%put _user_;
%mend mymacro;
%mymacro
%put The value of macro variable course outside MYMACRO is &course;
The SAS System
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: _TOMODS1
The value of the macro variable inside MYMACRO is STAT 4197
MYMACRO COURSE STAT 4197
GLOBAL COURSE STAT 6197
The value of macro variable course outside MYMACRO is STAT 6197
E3969440A681A2408885998500000006