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;

 
Current Models of Mountain Bicycles
Model Class Price Frame
Nor'easter Mountain $899 Aluminum
Santa Ana Mountain $459 Aluminum
Scirocco Mountain $2,256 Titanium

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 of the way the code is written, 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

Customer 28 Had the Single Largest Order
CustomerID OrderDate Model Quantity
28 21OCT00 Santa Ana 25
28 15OCT00 Santa Ana 15
28 15OCT00 Delta Breez .
28 21OCT00 Delta Breez .