# Lesson 33: SAS Macro Programming for Beginners

Lesson 33: SAS Macro Programming for Beginners

## Overview

This lesson introduces the most commonly used features of the SAS macro language. When you write a program that will be run over and over again, you might want seriously to consider using "macros" in your code, because:

• macros allow you to make a change in one location of your program, so that SAS can cascade the change throughout your program
• macros allow you to write a section of code once and use it over and over again, in the same program or even different programs
• macros allow you to make programs data driven, letting SAS decide what to do based on actual data values.

To whet our appetite for SAS macros, we'll read this paper:

SAS Macro Programming for Beginners

written by Susan J. Slaughter and Lora D. Delwiche and presented as a tutorial at the 2004 SAS Users Group International (SUGI) Meeting in Montreal, Canada.

## Objectives

Upon completion of this lesson, you should be able to:

• understand what a SAS macro is
• distinguish between local and global macro variables
• create a macro variable using a %LET assignment statement
• use a macro variable in a SAS program
• write and invoke a basic SAS macro
• write and invoke a SAS macro that uses parameters
• write a macro with conditional macro %IF-%THEN-%ELSE statements
• use and understand automatic macro variables such as &SYSDATE and &SYSDAY
• use CALL SYMPUT to write data-driven programs

## Textbook Reference

SAS Macro Programming for Beginners paper written by Susan J. Slaughter and Lora D. Delwiche.

# 33.1 - Lesson Notes

33.1 - Lesson Notes

### THE MACRO PROCESSOR

Page 1. You can refer to page 339 of our textbook for an example of a program that SAS would need to pre-process before executing the code. In that particular case, before executing the code, SAS would have to run the program through the macro processor in order to replace all the occurrences of "&NUMBER" with the value "5".

### SUBSTITUTING TEXT WITH %LET

Page 3. In case you want to try the program out on your own, here it is:

OPTIONS PS = 58 LS = 72 NODATE NONUMBER;

DATA models;
infile DATALINES truncover;
input Model $1-12 Class$ Price Frame$28-38; DATALINES; Black Bora Track 796 Aluminum Delta Breeze Road 399 CroMoly Jet Stream Track 1130 CroMoly Mistral Road 1995 Carbon Comp Nor'easter Mountain 899 Aluminum Santa Ana Mountain 459 Aluminum Scirocco Mountain 2256 Titanium Trade Wind Road 759 Aluminum ; RUN; %LET bikeclass = Mountain; *Use a macro variable to subset; PROC PRINT DATA = models NOOBS; where Class = "&bikeclass"; format Price dollar6.; title "Current Models of &bikeclass Bicycles"; RUN; You might also want to change the value of Mountain in the %LET statement to, say, Road, and re-run the program to see the effect. ### CREATING MODULAR CODE WITH MACROS Page 4. Again, in case you want to try the program out on your own, here it is: %MACRO printit; PROC PRINT data = models NOOBS; title 'Current Models'; var Model Class Frame Price; format Price dollar6.; RUN; %MEND printit; %printit PROC SORT data = models; by Price; RUN; %printit ### ADDING PARAMETERS TO MACROS Page 6. Here's the code for the example: %MACRO sortandprint(sortseq=, sortvar=); PROC SORT data = models; by &sortseq &sortvar; RUN; PROC PRINT data = models noobs; title 'Current Models'; title2 "Sorted by &sortseq &sortvar"; var Model Class Frame Price; format price dollar6.; RUN; %MEND sortandprint; %sortandprint(sortseq=Descending, sortvar=Price) %sortandprint(sortseq=, sortvar=Class) Page 7. Here's the code for the example with the MPRINT option invoked: OPTIONS MPRINT; %MACRO sortandprint(sortseq=, sortvar=); PROC SORT data = models; by &sortseq &sortvar; RUN; PROC PRINT data = models noobs; title 'Current Models'; title2 "Sorted by &sortseq &sortvar"; var Model Class Frame Price; format price dollar6.; RUN; %MEND sortandprint; %sortandprint(sortseq=Descending, sortvar=Price) %sortandprint(sortseq=, sortvar=Class) ### CONDITIONAL LOGIC Page 9. Here's the program: DATA orders; input CustomerID$ 1-3 @5 OrderDate date7. Model \$ 13-24 Quantity;
DATALINES;
287 15OCT03 Delta Breeze 15
287 15OCT03 Santa Ana    15
274 16OCT03 Jet Stream    1
174 17OCT03 Santa Ana    20
174 17OCT03 Nor'Easter    5
174 17OCT03 Scirocco      1
347 18OCT03 Mistral       1
287 21OCT03 Delta Breeze 30
287 21OCT03 Santa Ana    25
;
RUN;
%MACRO reports;
%IF &SYSDAY = Monday %THEN %DO;
PROC PRINT data = orders NOOBS;
format OrderDate date7.;
title "&SYSDAY Report: Current Orders";
RUN;
%END;
%ELSE %IF &SYSDAY = Friday %THEN %DO;
PROC TABULATE data = orders;
class CustomerID;
var Quantity;
table CustomerID ALL, Quantity;
title "&SYSDAY Report: Summary of Orders";
RUN;
%END;
%MEND reports;

%REPORTS
Note! Because the way the code is written, that if you don't run this program on a Monday or Friday, you will not get either of the pieces of output displayed in the paper. Just change either the Monday or the Friday in the code to the day that you are running the code, and you'll generate some output.

By the way, you might notice that I embedded the RUN; statements in the macro, rather than placing them outside of the macro as the authors of the paper did. Either approach works... it's just a matter of preference.

### DATA-DRIVEN PROGRAMS

Page 12. Here's the program:

*Sort by Quantity;
PROC SORT data = orders;
by descending Quantity;
RUN;

*Use CALL SYMPUT to find the biggest order;
DATA _NULL_;
set orders;
if _N_ = 1 then CALL SYMPUT("biggest", CustomerID);
else STOP;
RUN;

*Print all obs for customer with biggest order;
PROC PRINT data = orders NOOBS;
where CustomerID = "&biggest";
format OrderDate date7.;
title "Customer &biggest Had the Single Largest Order";
RUN

# 33.2 - Summary

33.2 - Summary

In this lesson, we learned how to use the SAS macro facility to write more flexible code.

The homework for this lesson will give you more practice with macros and macro variables so that you become even more familiar with how they work and can use them in your own SAS programming.

 [1] Link ↥ Has Tooltip/Popover Toggleable Visibility