Lesson 11, Part 1: Macros with Positional vs. Keyword Parameters¶

Why do we need macros?

"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.
In [51]:
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)
SAS Output

sashelp.class

Name Sex Age Height Weight
Alfred M 14 69.0 112.5
Alice F 13 56.5 84.0

sashelp.iris

Species SepalLength SepalWidth PetalLength PetalWidth
Setosa 50 33 14 2
Setosa 46 34 14 3
Setosa 46 36 10 2

sashelp.retail

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.
In [1]:
%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

Out[1]:
SAS Output

The SAS System

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

The SAS System

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

The SAS System

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.

In [7]:
*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)
Out[7]:
SAS Output

sashelp.class height 1

The MEANS Procedure

Analysis Variable : Height
N Mean Std Dev Minimum Maximum
19 62.3368421 5.1270752 51.3000000 72.0000000

sashelp.class height sex eq 'F'

The MEANS Procedure

Analysis Variable : Height
N Mean Std Dev Minimum Maximum
9 60.5888889 5.0183275 51.3000000 66.5000000

sashelp.class height sex eq 'M'

The MEANS Procedure

Analysis Variable : Height
N Mean Std Dev Minimum Maximum
10 63.9100000 4.9379370 57.3000000 72.0000000

sashelp.class weight 1

The MEANS Procedure

Analysis Variable : Weight
N Mean Std Dev Minimum Maximum
19 100.0263158 22.7739335 50.5000000 150.0000000

sashelp.class weight sex eq 'F'

The MEANS Procedure

Analysis Variable : Weight
N Mean Std Dev Minimum Maximum
9 90.1111111 19.3839137 50.5000000 112.5000000

sashelp.class weight sex eq 'M'

The MEANS Procedure

Analysis Variable : Weight
N Mean Std Dev Minimum Maximum
10 108.9500000 22.7271864 83.0000000 150.0000000

sashelp.shoes sales 1

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.

In [5]:
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)
Out[5]:

The SAS System

varlist: SYSPBUFF=(age, sex, weight, height)
Parentheses and commas deleted: age sex weight height
E3969440A681A2408885998500000008
In [6]:
* 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)
Out[6]:

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

In [9]:
*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

Give Your Macro Code an Extreme Makeover:Tips for even the most seasoned macro programmer By: Russ Tyndall

In [ ]:
* 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.

In [2]:
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;
SAS Output

The SAS System

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

Restriction: In open code, the ACTION that is associated with both the %THEN and %ELSE statements must be a %DO statement.

Below are two macros with no parameters.

In [3]:
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
In [4]:
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;
Out[4]:

                                                           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

https://v8doc.sas.com/sashtml/macro/z0206835.htm

In [3]:
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;
Out[3]:

                                                           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