sas lecture series sasmacros -...

74
sheepsqueezers.com Copyright ©2011 sheepsqueezers.com SAS Macros

Upload: others

Post on 27-Jul-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com

SAS Macros

Page 2: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com

This work may be reproduced and redistributed, in whole or in part, without alteration and without prior written permission, provided all copies contain the following statement:

Copyright ©2011 sheepsqueezers.com. This

work is reproduced and distributed with the

permission of the copyright holder.

Legal Stuff

This presentation as well as other presentations and documents found on the sheepsqueezers.com website may contain quoted material from outside sources such as books, articles and websites. It is our intention to diligently reference all outside sources. Occasionally, though, a reference may be missed. No copyright infringement whatsoever is intended, and all outside source materials are copyright of their respective author(s).

Page 3: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com

Intermediate SAS

SAS Lecture Series

SAS Macros Advanced SAS An Introduction

to SAS Programming

Page 4: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Charting Our Course

What’s that in the road, a head?

%Let me entertain you!

User-Defined vs. SAS-Defined Macro Variables and %PUT

The Simplest SAS Macro this Side of the Mason-Dixon Line

Some Nice SAS Options for Macro De-Lousing

A Comment about Comments

Using the SYMPUT AND SYMGET Functions

PROC SQL – SELECT INTO

More on Calling SAS Macros and Macro Parameters

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

Macro Functions – %SUBSTR, %TRIM, etc.

Two Additional Special Macro Functions: %EVAL and %SYSEVALF

One Very Funkified Macro Function: %SYSFUNC

What the Blank?!? When Nothing Means Something!

Macro Variable Indirection – When When && Is Is Good Good!

Macro Quoting – To %NRSTR Or Not to %NRSTR

The Data Step and Macros – RESOLVE and CALL EXECUTE

PARMBUFF and SYSPBUFF

%Local vs. %Global Macro Variables

More Automatic Macro Variables – SYSFILRC, SYSLIBRC, etc.

Examples of SAS Macro Code

Sharing Your SAS Macro Code with the Down-Trodden Masses

Page 5: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

What’s that in the Road, A Head?

The pressure’s on…your template is due…NOW! And you’re still programming …what’s the easiest thing to do? Cut-and-paste huge volumes of SAS code over and over and over and over…

Clearly this is not the way to go! Why? Error prone! Hard to Maintain! Hard to Modify! Hard to Understand!

Remember the saying: Work Smarter Not Harder!

SAS Macros allow you to repeat your SAS code with specified changes without having to cut-and-paste code over and over again. But this is its most basic functionality! SAS Macros can interact with your running DATA STEPs and PROC STEPs…we’ll learn more about this later on.

If you’ve never worked with SAS Macros before, you can think of them as a way to easily substitute parts of your SAS code -- DATA STEPs and PROC STEPs -- with text of your choice. (Think: Text Replacement!)

PROC PRINT DATA=SAMPLEXDATA_Q1;

VAR MONTH SAMPLEX_PATIENT_COUNTS;

TITLE1 "Samplex Report – Q1";

RUN;

Page 6: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%Let Me Entertain You!

Nearly everyone has seen a %Let statement before. This statement allows

you to associate a SAS macro variable with the text of your choice:

%Let myTitle=Millenium Samplex;

Here, the word myTitle is a SAS Macro Variable. You are associating the text Millenium Samplex with the SAS Macro Variable myTitle. You can replace the text Millenium Samplex anywhere it appears in your SAS program with the SAS Macro Variable myTitle as long as you prefix it with

an ampersand (&). The ampersand lets SAS know to replace that macro variable myTitle with your text Millenium Samplex.

For example,

PROC PRINT DATA=THE_FORMERLY_LIVING;

VAR MONTH PATIENT_COUNTS;

TITLE1 "&myTitle.";

RUN;

Note that there is an ampersand to the left of myTitle, but there also

appears to be a period to the right of it. This period is NOT the end of the sentence, but an indication to SAS that the macro variable name has been completely specified. If you want to have an actual period appear at the end of the sentence, place yet another period at the end of the title:

TITLE1 "&myTitle..";

Page 7: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%Let Me Entertain You!

Note that you don’t have to use SAS macro variables in just TITLEs. You can use them in SAS Code, too. In that case, there’s no need for double-quotes:

%Let myPersLib=SASOUT;

%Let myName=Bob;

%Let DrugName=SAMPLEX;

%Let year=2006;

%Let inSASDS=&myPersLib..&DrugName._&year.;

%Let outTxt=C:\MyStuff\&myName.\&DrugName..txt;

The macro variable inSASDB resolves to

SASOUT.SAMPLEX_2006

The macro variable outTxt resolves to

C:\MyStuff\Bob\SAMPLEX.txt

Note: If you use single-quotes/apostrophes/tick marks, the macro variable will NOT resolve. Use double-quotes!

filename outTxt "&outTxt.";

run;

data _null_;

file outTxt notitles noprint;

set &inSASDS.;

put …;

run;

Page 8: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%Let Me Entertain You!

Here is another example:

%Let FIVE=5;

%Let TEN=10;

%Let WHAT_IS_THIS=&TEN./&FIVE.;

data MyData;

num=&TEN./&FIVE.; /* WHAT IS THIS? */

output;

run;

The macro variable WHAT_IS_THIS resolves to the text 10/5 and NOT 2 as

you’d expect. Remember: TEXT REPLACEMENT. Macro variables do not automatically have mathematical operations performed on them.

On the other hand, the SAS dataset MyData contains one row and one variable, num, with the value of 2 and NOT the text 10/5.

[There are two functions that will allow

you to force calculations to be performed

on a SAS macro variable. More on that

later in the show…]

Note: Macro variables are stored in the macro symbol table.

Page 9: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

User-Defined vs. SAS-Defined Macro Variables and %PUT

When you create your own SAS macro variables, they are known as user-defined macro variables. SAS defines its own macro variables and are known as automatic macro variables.

You can display all of your user-defined macro variables by submitting the following code:

%put _user_;

The %put statement allows you to print out any one of your SAS macro variables and is useful for debugging a SAS macro:

%put ==>&TEN./&FIVE.<==; /* ==>10/5<== */

SAS creates its own macro variables, called automatic macro variables. A few useful automatic macro variables are:

%put &sysdate.; /* 11FEB07 */

%put &sysdate9.; /* 11FEB2007 */

%put &sysday.; /* Saturday */

%put &systime.; /* 15:27 */

%put &sysuserid; /* Bob */

To see all SAS-Defined Macro Variables, submit the following code:

%put _automatic_;

Page 10: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

The Simplest SAS Macro this Side of the Mason-Dixon Line

Now that we’ve had enough of SAS Macro Variables, it’s time to move on to SAS Macros themselves. Every SAS Macro begins with

%macro name-of-macro;

And ends with

%mend name-of-macro;

%macro PrintResults;

PROC PRINT DATA=SAMPLEXDATA_Q1;

VAR MONTH SAMPLEX_PATIENT_COUNTS;

TITLE1 "SAMPLEX Report – Q1";

RUN;

%mend PrintResults;

To "call" or "run" this macro, specify a percent sign followed by the name of the macro:

%PrintResults

Note that this macro is rather useless. Why?

Note: Notice there is no semi-colon at the end of the call to the macro (and it may even be detrimental in some cases to put one in).

Page 11: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

The Simplest SAS Macro this Side of the Mason-Dixon Line

Now that we’ve seen a really simple and worthless SAS Macro, let’s try to step it up a bit. Let’s allow our SAS Macro PrintResults to accept a parameter

for the quarter:

%macro PrintResults(qtr=);

PROC PRINT DATA=SAMPLEXDATA_&qtr.;

VAR MONTH SAMPLEX_PATIENT_COUNTS;

TITLE1 "SAMPLEX Report – &qtr.";

RUN;

%mend PrintResults;

Note that we added a left parenthesis, a variable named qtr followed by an equal sign and ended with a right parenthesis after the macro name. The variable qtr

is a SAS macro variable in disguise. Note that you resolve this SAS macro variable the same way we did in our %Let discussion above.

To call this SAS Macro, do the following:

%PrintResults(qtr=Q1)

%PrintResults(qtr=Q2)

%PrintResults(qtr=Q3)

SAS will replace any occurrence of the SAS macro variable qtr with Q1, then Q2, then Q3, etc. Can you see the value in using SAS Macros yet??

Page 12: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Some Nice SAS Options for Macro De-Lousing

Here is the SAS Log file after you run your SAS macro PrintResults:

127

128 %macro PrintResults(qtr=);

129

130 PROC PRINT DATA=SAMPLEXDATA_&qtr.;

131 VAR MONTH SAMPLEX_PATIENT_COUNTS;

132 TITLE1 "SAMPLEX Report – &qtr.";

133 RUN;

134

135 %mend PrintResults;

136 %PrintResults(qtr=Q1)

NOTE: There were 3 observations read from the data set WORK.SAMPLEXDATA_Q1.

NOTE: PROCEDURE PRINT used (Total process time):

real time 0.00 seconds

cpu time 0.00 seconds

137 %PrintResults(qtr=Q2);

NOTE: There were 3 observations read from the data set WORK.SAMPLEXDATA_Q2.

NOTE: PROCEDURE PRINT used (Total process time):

real time 0.00 seconds

cpu time 0.01 seconds

Notice that there isn’t much in the way of "debugging" information. There are 3 nice options related to SAS Macros that allow you to debug SAS Macros more easily.

Page 13: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Some Nice SAS Options for Macro De-Lousing

OPTIONS MPRINT SYMBOLGEN MLOGIC MLOGICNEST MPRINTNEST;

MPRINT – prints out the contents of the SAS Macro as the macro is running.

SYMBOLGEN – shows each SAS macro/parameter as it’s being resolved

MLOGIC – prints out information related to %IF logic…more on this later.

163

164 %macro PrintResults(qtr=);

165

166 PROC PRINT DATA=SAMPLEXDATA_&qtr.;

167 VAR MONTH SAMPLEX_PATIENT_COUNTS;

168 TITLE1 "SAMPLEX Report – &qtr.";

169 RUN;

170

171 %mend PrintResults;

172 %PrintResults(qtr=Q1)

MLOGIC(PRINTRESULTS): Beginning execution.

MLOGIC(PRINTRESULTS): Parameter QTR has value Q1

SYMBOLGEN: Macro variable QTR resolves to Q1

MPRINT(PRINTRESULTS): PROC PRINT DATA=SAMPLEXDATA_Q1;

MPRINT(PRINTRESULTS): VAR MONTH SAMPLEX_PATIENT_COUNTS;

SYMBOLGEN: Macro variable QTR resolves to Q1

MPRINT(PRINTRESULTS): TITLE1 "SAMPLEX Report – Q1";

MPRINT(PRINTRESULTS): RUN;

NOTE: There were 3 observations read from the data set WORK.SAMPLEXDATA_Q1.

NOTE: PROCEDURE PRINT used (Total process time):

real time 0.00 seconds

cpu time 0.01 seconds

MLOGIC(PRINTRESULTS): Ending execution.

Page 14: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Some Nice SAS Options for Macro De-Lousing

OPTIONS MPRINT SYMBOLGEN MLOGIC MLOGICNEST MPRINTNEST;

MPRINTNEST – prints out macro nesting information. Must have MPRINT turned on as well.

MLOGICNEST – prints out macro nesting information. Must have MLOGIC turned on as well.

13 options mprint symbolgen mlogic mlogicnest mprintnest;

14 run;

15

16 %macro Outer;

17 %Inner;

18

19 %if 1=1 %then %do;

20 data _null_;

21 a=1;

22 run;

23 %end;

24

25 %mend Outer;

26

27 %macro Inner;

28 %Let bob=7;

29 %mend Inner;

30

31 %Outer

…continued…

Page 15: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Some Nice SAS Options for Macro De-Lousing

OPTIONS MPRINT SYMBOLGEN MLOGIC MLOGICNEST MPRINTNEST;

MPRINTNEST – prints out macro nesting information. Must have MPRINT turned on as well.

MLOGICNEST – prints out macro nesting information. Must have MLOGIC turned on as well.

MLOGIC(OUTER): Beginning execution.

MLOGIC(OUTER.INNER): Beginning execution.

MLOGIC(OUTER.INNER): %LET (variable name is BOB)

MLOGIC(OUTER.INNER): Ending execution.

MPRINT(OUTER): ;

MLOGIC(OUTER): %IF condition 1=1 is TRUE

MPRINT(OUTER): data _null_;

MPRINT(OUTER): a=1;

MPRINT(OUTER): run;

NOTE: DATA statement used (Total process time):

real time 0.00 seconds

cpu time 0.00 seconds

MLOGIC(OUTER): Ending execution.

Page 16: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

A Comment about Comments

You can place comments inside your SAS macros using either standard SAS comments, or macro-specific comments. SAS recommends using the macro-specific comments within a SAS macro:

%macro PrintResults(qtr=);

%*----------------------------------------*;

%* Lovingly print out the dataset. *;

%*----------------------------------------*;

PROC PRINT DATA=SAMPLEXDATA_&qtr.;

VAR MONTH SAMPLEX_PATIENT_COUNTS;

TITLE1 "SAMPLEX Report – &qtr.";

RUN;

%mend PrintResults;

SAS macro comments begin with a percent and end with a semi-colon.

Note that putting an asterisk in front of a %Let will not hide it from the macro processor:

*%Let bob=5;

SAS macro processor will still associate 5 with bob, unlike these which will hide it:

%*%Let bob=5;

/* %Let bob=5; */

or the ever popular: *Let bob=5;

Page 17: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Using the SYMPUT AND SYMGET Functions

NOTE: Numeric values have been converted to character values at the places given by:

(Line):(Column).

609:24

NOTE: There were 1 observations read from the data set WORK.TOTAL_SAMPLEX_PATIENT_COUNTS.

NOTE: DATA statement used (Total process time):

real time 0.05 seconds

cpu time 0.02 seconds

SYMBOLGEN: Macro variable TOTPATS resolves to 65

611 %put ==>&TOTPATS.<==;

==> 65<==

As we’ve seen above, you can create SAS macro variables using the %Let

statement. Eventually, though, you’ll have the need to create a SAS macro variable based on information within a Data Step. In this case, then, the %Let statement is worth crap. SAS provides the CALL SYMPUT function that you can

use within a Data Step to create your SAS macro variable.

proc means data=SAMPLEXDATA_Q1 nway noprint;

var SAMPLEX_PATIENT_COUNTS;

output out=Total_SAMPLEX_Patient_Counts(drop=_type_ _freq_)

sum(SAMPLEX_PATIENT_COUNTS)=Total_Pats;

run;

data _null_;

set Total_SAMPLEX_Patient_Counts; /* Assumes dataset has ONLY one row! */

call symput('TOTPATS',Total_Pats);

run;

%put ==>&TOTPATS.<==;

Page 18: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Using the SYMPUT AND SYMGET Functions

The CALL SYMPUT() function takes two parameters. The first parameter is

a string containing the name of the macro variable you want to create. The second parameter is the actual value of the macro variable. Think of the first parameter as the macro variable name after a %Let, and the second parameter is

the data after the equal sign.

Note in the SAS Log output that you are told that numeric values are being converted to character values. This message is being issued since the second parameter, in this case, is a number rather than text. Also, note that when we %put the macro variable TOTPATS, that there appear to be some spaces before the

actual value.

To eliminate the first message, use a PUT() function, or just don’t worry about it:

data _null_;

set Total_SAMPLEX_Patient_Counts;

call symput('TOTPATS',trim(left(put(Total_Pats,15.))));

run;

NOTE: The macro variable is ONLY available AFTER the Data Step completes!!

You can eliminate the second issue by using the TRIM() and LEFT() functions. In this case:

data _null_;

set Total_SAMPLEX_Patient_Counts;

call symput('TOTPATS',trim(left(Total_Pats)));

run;

Page 19: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Using the SYMPUT AND SYMGET Functions

The SYMGET() function takes one parameter, the name of an existing SAS macro,

and returns the value of the SAS macro as a character string. You use this within a SAS Data Step. For example,

%Let FIVE=5;

%Let TEN=10;

%Let WHAT_IS_THIS=&TEN./&FIVE.; /* 10/5 */

data MyData;

length myMacVar $ 4;

MyMacVar=symget('WHAT_IS_THIS');

run;

Note that you can build the parameter string based on your data:

data MyData;

length myMacVar $ 200;

set MyData;

MyMacVar=symget('MV'||left(_n_)); /* MV1, MV2, MV3, … */

run;

Note that you can use CALL SYMPUT() to assign several macro variables in a

similar way:

call symput('MV' || left(_n_) , left(Monthly_Counts) );

Page 20: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

PROC SQL – SELECT INTO

As we’ve seen, you can create SAS macro variables using %Let and the CALL SYMPUT() function. You can create SAS macro variables using PROC SQL as well!

proc sql noprint;

select Total_Patients

into :totpats

from Total_SAMPLEX_Patient_Counts;

quit;

But, you can also accumulate several rows worth of data into one macro variable. Let’s assume we have a SAS dataset with 5 NDC codes. Say we want to create one SAS macro variable containing a comma-delimited list of NDC codes each with apostrophes around them:

proc sql noprint;

select "’" || NDC_KEY || "’"

into :AllNDCs separated by ‘,’

from My_Five_NDC_Codes;

quit;

%put ==>&AllNDCs.<==;

==>'11111111111','22222222222','33333333333','44444444444','55555555555'<==

Sweet, huh? But, don’t go crazy!! If you have more than a handful of NDC codes, it’s probably better to load them into a database table and perform a JOIN.

Page 21: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

PROC SQL – SELECT INTO

Note that you can accumulate the rows of a variable in a SAS dataset into macro variables in one PROC SQL statement. For example,

data NDCList;

NDC_KEY="11111111111";output;

NDC_KEY="22222222222";output;

NDC_KEY="33333333333";output;

run;

proc sql noprint;

select NDC_KEY

into :ndc1-:ndc3

from NDCList;

run;

%put ==>&ndc1.<==;

%put ==>&ndc2.<==;

%put ==>&ndc3.<==;

Note that you can also include many variables on the SELECT line:

proc sql noprint;

select NDC_KEY,AGE_KEY,PATIENT_KEY

into :ndc1-:ndc3,:age1-:age3,:patkey1-:patkey3

from NDCList;

run;

Page 22: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

PROC SQL – SELECT INTO

Important Note:

PROC SQL will use the BEST12. SAS Format on a number before putting it into the

macro variable. This may cause problems:

data LargeNumber;

num=123456789;

run;

proc sql noprint;

select num

into :num

from LargeNumber;

quit;

%put ==>&num.<==;

==>1.2346E8<==

Best to do this:

proc sql noprint;

select put(num,15.)

into :num

from LargeNumber;

quit;

%put ==>&num.<==;

==> 123456789<==

Page 23: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

More on Calling SAS Macros and Macro Parameters

As we’ve seen, you can call a SAS macro with no parameters or with parameters. There are two types of macro parameters you can use when creating your own macro: Keyword Parameters or Positional Parameters. In either case, your parameters are delimited by commas.

Note that each parameter ends with an equal sign. When you call your macro using Keyword Parameters, the order of the parameters is unimportant. This is in contrast to Positional Parameters where the order is important:

%macro PullData(StartDate,EndDate,NDCDataSet);

…code goes here…

/* Use &StartDate., &EndDate., and &NDCDataSet. */

%mend PullData;

%PullData(01JAN2006,31DEC2006,SASOUT.NDCList)

The following macro uses Keyword Parameters for StartDate, EndDate and NDCDataSet:

%macro PullData(StartDate=,EndDate=,NDCDataSet=);

…code goes here…

/* Use &StartDate., &EndDate., and &NDCDataSet. */

%mend PullData;

%PullData(StartDate=01JAN2006,EndDate=31DEC2006,NDCDataSet=SASOUT.NDCList)

Page 24: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

More on Calling SAS Macros and Macro Parameters

We recommend that you use Keyword Parameters over Positional Parameters since Keyword Parameters allow you to specify default values, such as:

%macro PullData(StartDate=01JAN2006,EndDate=31DEC2006,NDCDataSet=);

…code goes here…

/* Use &StartDate., &EndDate., and &NDCDataSet. */

%mend PullData;

Notice how the default value of StartDate is set at 01JAN2006 and the default value of EndDate is set to 31DEC2006. If you want to use the default values in the

call to the macro, you can call the macro like this:

%PullData(NDCDataSet=SASOUT.NDCList)

You can combine both Keyword and Positional Parameters in your macro…but only a homicidal maniac wearing a kilt would do that.

Page 25: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

Recall that in the Data Step, you have the ability to perform looping using DO…END, If Statements using IF…THEN…ELSE IF, while Loops using the Do While statement, and until Loops using the Do Until statement. Believe it or not, these

same constructs are available in the SAS Macro Language.

%If-%Then-%Else Macro Statement

%IF (expression) %THEN %DO;

/* additional data step and procedure statements */

%END;

%ELSE %IF (expression) %THEN %DO;

/* additional data step and procedure statements */

%END;

%ELSE %DO;

/* additional data step and procedure statements */

%END;

For example, suppose that you want to issue certain SAS Data Steps and Procedures based on whether the SAS code is being run on one SAS Enterprise Guide server versus another. In order to determine the machine, you can use the SAS Automatic Macro Variable _EGHOSTNAME which specifies the IP Address of the

machine your SAS code is running on. For example, when you the following code to 192.168.111.222,

%put ==>&_EGHOSTNAME.<==;

==>192.168.111.222<==

Page 26: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

%If-%Then-%Else Macro Statement (continued)

%macro PullData(StartDate=,EndDate=,NDCDataSet=);

%if &_EGHOSTNAME. eq 192.168.111.222 %then %do;

/* Run 192.168.111.222-specific SAS code */

%put ==>192.168.111.222!<==;

%end;

%else %if &_EGHOSTNAME. eq 192.168.111.333 %then %do;

/* Run 192.168.111.333-specific SAS code */

%put ==>192.168.111.333!<==;

%end;

%else %if &_EGHOSTNAME. eq 192.168.111.444 %then %do;

/* Run 192.168.111.444-specific SAS code */

%put ==>192.168.111.444!<==;

%end;

%mend PullData;

%PullData(StartDate=01JAN2006,EndDate=31DEC2006,NDCDataSet=SASOUT.Bob)

Take note of the "eq". This means equals. You can use an equal sign (=) if you want to. The relational/logical operators are: eq, ne, gt, ge, lt, le, ne, AND, OR, NOT.

If we run this code on 192.168.111.222, the text ==>192.168.111.222!<== will

appear in the log.

Page 27: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

%If-%Then-%Else Macro Statement (continued)

Before we move on to the other control structures, I’d like to show you what the SAS System Option MLOGIC produces in the SAS Log File when you use an %IF

statement:

MLOGIC(PULLDATA): Beginning execution.

MLOGIC(PULLDATA): Parameter STARTDATE has value 01JAN2006

MLOGIC(PULLDATA): Parameter ENDDATE has value 31DEC2006

MLOGIC(PULLDATA): Parameter NDCDATASET has value SASOUT.BOB

SYMBOLGEN: Macro variable _EGHOSTNAME resolves to 127.0.0.1

SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been

unquoted for printing.

MLOGIC(PULLDATA): %IF condition &_EGHOSTNAME. eq 127.0.0.1 is TRUE

MLOGIC(PULLDATA): %PUT ==>127.0.0.1!<==

==>127.0.0.1!<==

MLOGIC(PULLDATA): Ending execution.

Take note of the highlighted line above. When MLOGIC is turned on, the SAS Macro processor will indicate whether your %IF statement is TRUE or FALSE.

Note that the results from MLOGIC, SYMBOLGEN and MPRINT come at a price: slower performance. It is recommended that you turn off these options after you have completely deloused your macro.

Page 28: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

Why a Semicolon at the End of a Macro Invocation Can Cause Problems

As we’ve said before, don’t put a semicolon at the end of a SAS Macro’s invocation. Most of the time, actually, you can put a semicolon at the end of the invocation. But, there are certain instances where it will cause you hours of endless trouble.

Let’s create a macro whose sole purpose is to return a list of variables based on our parameter choice:

%macro MyFavoriteVars(type=);

%if &type. eq 1 %then %do;

PAT_SEX,PRACT_SEX,REF_PRACT_SEX,ALIEN_SEX

%end;

%else %if &type. eq 2 %then %do;

PATIENT_KEY,PRACTITIONER_KEY,NDC_KEY,DAW_KEY

%end;

%mend MyFavoriteVars;

%MyFavoriteVars(type=2)

Notice that there are 4 variables just hanging out. We can call this macro in places like this:

proc sql;

select %MyFavoriteVars(type=2)

from bob;

quit;

When run, this resolves to the following code:

Page 29: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

Why a Semicolon at the End of a Macro Invocation Can Cause Problems

proc sql;

select PATIENT_KEY,PRACTITIONER_KEY,NDC_KEY,DAW_KEY

from bob;

quit;

Sweet! But, let’s try that again with the semicolon at the end:

proc sql;

select %MyFavoriteVars(type=2);

from bob;

quit;

You get the following error message:

14 select %MyFavoriteVars(type=2);

_

76

ERROR 76-322: Syntax error, statement will be ignored.

SAS sees

SELECT PATIENT_KEY,PRACTITIONER_KEY,NDC_KEY,DAW_KEY;

now! Not good! So, this is an instance where that semicolon is bad!

Page 30: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

%DO Loop Macro Statement

The SAS Macro Language provides a looping construct similar to the DO…END looping construct in the Data Step. The example of the %DO Loop is:

%do i=1 %to 10;

%put ==>The number is &i.<==;

%end;

Take note of the %-sign before the TO. If you want to skip over numbers, you can use the %BY syntax. Here the numbers 1,3,5,7,9 print out.

%do i=1 %to 10 %by 2;

%put ==>The number is &i.<==;

%end;

In the Data Step version of the Do-Loop, you can enter in a comma-delimited list of values. This is not the case for the macro %DO-Loop.

Suppose you want to create a separate SAS Dataset containing rows of data for each NDC in your large dataset. The next slide shows an example of how to do this…

Page 31: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%macro CreateNDCDataSets(InData=,OutData=);

/* Create a dataset containing unique NDC_KEYs */

proc sort data=&InData.(keep=NDC_KEY) out=NDCList nodupkey;

by NDC_KEY;

run;

/* Determine how many rows (or NDC_KEYs) are in NDCList */

proc sql noprint;

SELECT count(*)

INTO :ndccnt

FROM NDCList;

quit;

/* For each individual NDC_KEY in NDCList, create a separate SAS dataset */

%do i=1 %to &ndccnt.;

/* get this iteration`s NDC_KEY */

data _null_;

rownum=&i.;

set NDCList point=rownum;

call symput("thisNDC",NDC_KEY);

stop; /* VERY IMPORTANT TO HAVE THIS HERE WHEN USING POINT=!! */

run;

/* Write out this iteration`s dataset */

data &OutData._&thisNDC.;

set &InData.(where=(NDC_KEY="&thisNDC."));

run;

%end;

%mend CreateNDCDataSets;

%CreateNDCDataSets(InData=SASOUT.SAMPLEX,OutData=SASOUT.SAMPLEX)

Page 32: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Control Structures – %IF, %DO, %DO %WHILE, etc.

%DO %WHILE Loop Macro Statement

The SAS Macro Language provides a while loop construct similar to the DO WHILE …END looping construct in the Data Step. The syntax for the %DO %WHILE Loop is:

%do %while(expression);

/* Additional Data Step and Procedures code here */

%end;

Here is an example that prints out the first N positive integers:

%macro PrintNums(N=);

%Let iter=1;

%do %while(&iter. le &N.);

%put ==>&iter.<==;

%Let iter=%eval(&iter. + 1); /* More on this later… */

%end;

%mend PrintNums;

%PrintNums(N=5)

It’s very possible to get into an infinite loop with the %DO %WHILE loop. Check your

expression carefully and save your SAS code!!

The %DO %WHILE loop will loop until expression is false. Unlike a %DO %UNTIL, the %DO %WHILE loop will not execute at all if the expression is False to begin with.

Page 33: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Functions – %SUBSTR, %TRIM, %SCAN, etc.

The SAS Macro Language provides some functions used specifically with the SAS Macro Language. Some of these functions are familiar to you because they have a Data Step equivalent. Some of them won’t be familiar especially if you’ve never seen them before.

%CMPRES(arg) – compresses blanks to a single blank and removes leading and

trailing blanks

%INDEX(source,string) – Returns the position within source of the first

character specified in the string.

%LEFT(arg) – Left trims argument

%LENGTH(arg) – returns the length of arg

%LOWCASE(arg) – returns arg with all upper-case letters changed to lower-case

%SCAN(arg,N,delimiters) – returns the Nth word in arg delimited by the optional

delimiters (defaults to blank,period,comma,pipe, etc.)

%SUBSTR(arg,start,len) – returns a substring of arg starting at start for a

length of len.

%TRIM(arg) – trims trailing blanks from arg

%UPCASE(arg) – returns arg with all lower-case letters changed to upper-case

Page 34: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Functions – %SUBSTR, %TRIM, %SCAN, etc.

Notice that I did not specify any delimiters. A blank is one of %SCAN’s default

delimiters. The result looks like:

==>SAMPLEX<==

==>Samplex<==

==>PULMICORT<==

==>VIAGRA<==

==>ASPIRIN<==

What do you do if you don’t know ahead of time the number of brands?

Some SAS Macro functions take their parameters a little bit differently from their corresponding Data Step comrades. For example, here is how we would use the %SCAN function within a SAS Macro:

%macro ParseBrandNames;

/* Create a list of Brand Names */

%Let BrandNames=SAMPLEX Samplex PULMICORT VIAGRA ASPIRIN;

/* Get each brand name from the macro variable BrandNames */

%do i=1 %to 5;

%put ==>%scan(&BrandNames.,&i.)<==;

%end;

%mend ParseBrandNames;

%ParseBrandNames

Page 35: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Two Special Macro Functions: %EVAL and %SYSEVALF

There are two additional macro functions which you should be aware of. Recall that in our example of the %DO %WHILE above, I used the %EVAL() function:

%do %while(&iter. le &N.);

%put ==>&iter.<==;

%Let iter=%eval(&iter. + 1);

%end;

To return a number with the fractional part, use %SYSEVALF:

%Let Two_Point_Five=%sysevalf(5/2);

%put ==>&Two_Point_Five.<==;

==>2.5<==

The %EVAL function evaluates an arithmetic expression using INTEGER arithmetic.

What this means is that any fractional part in a calculation is chopped. In the above example, &iter. resolves to a number (say, 5), and then one is being added to it. But, in order for the SAS Macro processor to return the number 6 instead of the character string "5 + 1", you must use the %EVAL function.

Here is an example of a calculation that would normally return a number with a fractional part:

%Let Two_Point_Five=%eval(5/2);

%put ==>&Two_Point_Five.<==;

==>2<==

Page 36: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Two Special Macro Functions: %EVAL and %SYSEVALF

Important Notes

All parts of the macro language that evaluate expressions, like the

%IF (expression) %THEN…

%DO I=expression %TO expression %BY expression

%DO %WHILE(expression) …

%DO %UNTIL(expression) …

%SCAN(arg,expression) …

actually call the %EVAL function for you automatically. For example,

%do %while(&iter. le &N.);

%put ==>&iter.<==;

%Let iter=%eval(&iter. + 1);

%end;

Notice that there is no need to wrap &iter. le &N. in a %EVAL function.

Page 37: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Two Special Macro Functions: %EVAL and %SYSEVALF

Important Notes

The %SYSEVALF function takes an optional second parameter:

BOOLEAN – returns 0 if the expression is 0 or missing; otherwise, 1

CEIL – returns the ceiling of the expression

FLOOR – returns the floor of the expression

INTEGER – returns FLOOR if expression if positive and CEIL is negative.

For example: %Let Two_Point_Five=%sysevalf(5/2,floor);

%put ==>&Two_Point_Five.<==;

==>2<==

%Let Two_Point_Five=%sysevalf(5/2,ceil);

%put ==>&Two_Point_Five.<==;

==>3<==

%Let Two_Point_Five=%sysevalf(5/2,integer);

%put ==>&Two_Point_Five.<==;

==>2<==

%Let Two_Point_Five=%sysevalf(-5/2,integer);

%put ==>&Two_Point_Five.<==;

==>-2<==

%Let Two_Point_Five=%sysevalf(5/2,boolean);

%put ==>&Two_Point_Five.<==;

==>1<==

Page 38: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

One Very Funkified Macro Function: %SYSFUNC

So far, you are probably not very impressed by the number of functions available within the SAS Macro Language. Suppose I want to use the INTNX function to do intnx-like things. Unfortunately, the INTNX function as well as many of the nifty

functions available in the Data Step are NOT available natively to the SAS Macro Language.

Note that you cannot perform calculations within a %SYSFUNC:

%Let PI=%sysfunc( 4*atan(1) ); /* WRONG! */

%Let PI=%sysevalf( 4 * %sysfunc( atan(1) ) ); /* RIGHT! */

%put ==>&PI.<==;

==>3.14159265358976<==

This is where %SYSFUNC comes in. This macro function allows you to pass it a

Data Step function name along with that function’s parameter(s) and it’ll operate just like a native SAS Macro Language function. For example, to use the EXP() function to get exp(1), do this:

%Let E=%sysfunc( exp(1) );

%put ==>&E.<==;

==>2.71828182845904<==

Also, you cannot nest functions as you can in the Data Step: %Let CrazyNum=%sysfunc( sin(cos(5)) ); /* WRONG! */

%Let CrazyNum=%sysfunc( sin( %sysfunc( cos(5) ) ) ); /* RIGHT! */

Page 39: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

One Very Funkified Macro Function: %SYSFUNC

The following functions are NOT available via the %SYSFUNC macro function: DIF, DIM, HBOUND, IORCMSG, INPUT, LAG, LBOUND, MISSING, PUT, RESOLVE, SYMGET, among

others.

Note that you cannot use the PUT and INPUT functions with the macro function %SYSFUNC, but you can use the PUTN and INPUTN functions. Recall that these two functions (along with PUTC and INPUTC), allow you to determine the format/informat

you want to use AT RUNTIME.

For some Enterprise Guide projects, you may need to use dates. This is the method that I use. I create one code module (I usually call it LoadProjectGlobals) in EG and

create all of the macro variables I will use throughout the entire project. Here is an example LoadProjectGlobals looks like:

%Let mstrCurrentCycle=02/01/2007; /* MM/DD/YYYY FORMAT */

%put ===>Current Cycle Date as String: &mstrCurrentCycle.<===;

===>Current Cycle Date as String: 02/01/2007<===

%Let mdtCurrentCycle=%sysfunc(inputn(&mstrCurrentCycle.,mmddyy10.));

%put ===>SAS Date Value (Current Cycle): &mdtCurrentCycle.<===;

===>SAS Date Value (Current Cycle): 17198<===

%Let mdtStartDate=%sysfunc(intnx(month,%sysfunc(inputn(&mstrCurrentCycle.,mmddyy10.)),-1,B));

%put ===>SAS Date Value (Start Date): &mdtStartDate.<===;

===>SAS Date Value (Start Date): 17167<===

%Let mstrStartDate=%sysfunc(putn(&mdtStartDate.,mmddyy10.));

%put ===>SAS Date as String (Start Date): &mstrStartDate.<===;

===>SAS Date as String (Start Date): 01/01/2007<===

Page 40: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

What the Blank?!? When Nothing Means Something! Recall the code we used to show off the %SCAN SAS macro function:

%macro ParseBrandNames;

/* Create a list of Brand Names */

%Let BrandNames=SAMPLEX Samplex PULMICORT VIAGRA ASPIRIN;

/* Get each brand name from the macro variable BrandNames */

%do i=1 %to 5;

%put ==>%scan(&BrandNames.,&i.)<==;

%end;

%mend ParseBrandNames;

Another way to do the same thing without having to specify the number (5) of brands, is to use a %DO %WHILE loop. Pay attention to the blue line and the blank space after the ne relational operator. This is a comparison to a blank!

%macro ParseBrandNames(BrandNames=);

/* Initialize the first iteration`s brand */

%Let thisIter=1;

%Let thisBrand=%scan(&BrandNames.,&thisIter.);

%do %while(&thisBrand. ne );

%put ==>&thisBrand.<==;

%Let thisIter=%eval(&thisIter. + 1);

%Let thisBrand=%scan(&BrandNames.,&thisIter.);

%end;

%mend ParseBrandNames;

%ParseBrandNames(BrandNames=SAMPLEX Samplex PULMICORT VIAGRA ASPIRIN SPIRIVA DESINEX)

Page 41: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Variable Indirection – When When && Is Is Good Good!

Suppose you create the following macro variables:

%Let B1=SAMPLEX;

%Let B2=Samplex;

%Let B3=PULMICORT;

%Let BTOT=3;

Next, suppose you want to use a %DO Loop to iterate through all three macro variables and print out their values:

%macro PrintIt;

%do i=1 %to &BTOT.;

%put ==>B&i.<==;

%end;

%mend PrintIt;

%PrintIt;

Will you get a list of the brand name? Unfortunately, no. You will get the following: ==>B1<==

==>B2<==

==>B3<==

Suppose you change your %put to this:

%put ==>&B&i.<==;

Page 42: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

Macro Variable Indirection – When When && Is Is Good Good!

%macro PrintIt;

%do i=1 %to &BTOT.;

%put ==>&B&i.<==;

%end;

%mend PrintIt;

%PrintIt

This time, SAS complains and puts the following message in the SAS Log:

WARNING: Apparent symbolic reference B not resolved.

In order to print out the brand names, you must put TWO ampersands before the B, not just one:

%macro PrintIt;

%do i=1 %to &BTOT.;

%put ==>&&B&i.<==;

%end;

%mend PrintIt;

%PrintIt

==>SAMPLEX<==

==>Samplex<==

==>PULMICORT<==

This is called indirection and is very useful, as you will see in the next example.

Page 43: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%macro CreateNDCDataSets(InData=,OutData=);

/* Create a dataset containing unique NDC_KEYs */

proc sort data=&InData.(keep=NDC_KEY) out=NDCList nodupkey;

by NDC_KEY;

run;

/* Create one SAS macro variable for each NDC_KEY in NDCList */

data _null_;

set NDCList end=lastcase;

call symput("N"||left(_n_),NDC_KEY);

if lastcase then call symput("N0",_n_);

run;

/* For each individual NDC_KEY in NDCList, create a separate SAS dataset */

%do i=1 %to &N0.;

/* Write out this iteration`s dataset */

data &OutData._&&N&i.;

set &InData.(where=(NDC_KEY="&&N&i."));

run;

%end;

%mend CreateNDCDataSets;

%CreateNDCDataSets(InData=SASOUT.SAMPLEX,OutData=SASOUT.SAMPLEX)

Recall this example from the section on the %Do Loop Control Structure.

Note that you can have more levels of indirection (more than two &s), but we suggest you avoid this in order to keep your sanity.

Macro Variable Indirection – When When && Is Is Good Good!

Page 44: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Occasionally, in the SAS Log, you’ll see the message:

SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been

unquoted for printing.

Macro Quoting – To %NRSTR Or Not to %NRSTR

Macro quoting is used to prevent unintended resolution of what the SAS Macro processor may interpret as a SAS macro variable or a SAS macro. For example, if we submit this code, what do you think will happen?

%Let PharmaCompany=J&J;

In the SAS Log you will see the warning message:

WARNING: Apparent symbolic reference J not resolved.

The SAS Macro processor is misinterpreting the &J in J&J as a SAS Macro variable and it is trying to resolve the J when it can’t find it. What do you think will happen

if we submit the following code?

%Let Drug=MEPERIDINE 5%SOLN/10MG;

In the SAS Log you will see this warning message:

WARNING: Apparent invocation of macro SOLN not resolved.

In this case, the SAS Macro processor thinks that SOLN is a SAS Macro and is trying

to run it. Clearly, we cannot live like this!! This is where the macro quoting functions come in to play.

Page 45: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com There are several SAS macro quoting functions, but the one I use most, is %NRSTR,

which stands for No Resolution STRING. This will prevent any ampersands and percent signs from being incorrectly interpreted. Here it is in action:

%Let PharmaCompany=%nrstr(J&J);

%Let Drug=%nrstr(MEPERIDINE 5%SOLN/10MG);

Macro Quoting – To %NRSTR Or Not to %NRSTR

When you submit these lines to SAS, you will not receive warning messages in the SAS Log. You resolve these macro variables as you would normally in your SAS macro code: pre-fixing with an ampersand and post-fixing with a period.

Another place you may need a SAS macro quoting function is if you are passing comma-delimited values to a macro parameter. Recall that two or more parameters must be comma-delimited when defining a SAS macro. If one or your parameters is receiving a comma-delimited list of values, you can confuse the SAS Macro processor. Here is an example:

%macro DrugPrint(DrugList=,thisDrugNbr=);

%put ==>%scan(&DrugList.,&thisDrugNbr.)<==;

%mend DrugPrint;

%DrugPrint(DrugList=SAMPLEX,Samplex,PULMICORT,VIAGRA,thisDrugNbr=2)

Try this:

%DrugPrint(DrugList=%nrstr(SAMPLEX,Samplex,PULMICORT,VIAGRA),thisDrugNbr=2)

Similar problems may arise in calls to macro function, such as %SCAN.

Page 46: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Note that this breaks down when we really want a macro variable to resolve in the parentheses. For example:

%macro DrugPrint(DrugList=,thisDrugNbr=);

%put ==>%scan(&DrugList.,&thisDrugNbr.)<==;

%mend DrugPrint;

%Let Drug1=SAMPLEX;

%Let Drug2=Samplex;

%Let Drug3=PULMICORT;

%Let Drug4=VIAGRA;

%DrugPrint(DrugList=%nrstr(&Drug1.,&Drug2.,&Drug3.,&Drug4.),thisDrugNbr=2)

==>Drug2<== is the output when we really want it to be Samplex. The %SCAN function uses these as default delimiters: blank . < ( + & ! $ * ); ^ − / , % |

Use %str() instead:

%DrugPrint(DrugList=%str(&Drug1.,&Drug2.,&Drug3.,&Drug4.),thisDrugNbr=2)

==>Samplex<==

To summarize, %NRSTR() prevents macro variable and macro resolution of any kind, whereas %STR() does allow macro variable and macro resolution. Both will "quote" the string to prevent – in the example above – the DrugList being

interpreted as multiple parameters in the macro call.

Macro Quoting – To %NRSTR Or Not to %NRSTR

Page 47: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Note that there is further trouble if you have unbalanced quotation marks:

%macro DrugPrint(DrugList=,thisDrugNbr=);

%put ==>%scan(&DrugList.,&thisDrugNbr.)<==;

%mend DrugPrint;

%Let Drug1=SAMPLEX;

%Let Drug2=Samplex;

%Let Drug3=PULMICORT;

%Let Drug4=BOB’s;

%DrugPrint(DrugList=%str(&Drug1.,&Drug2.,&Drug3.,&Drug4.),thisDrugNbr=4)

WARNING: The quoted string currently being processed has become more than 262

characters long. You may have unbalanced quotation marks.

To fix this, we can use %STR() to surreptitiously put in an apostrophe into Drug4:

%Let Drug4=BOB%str(%’)s; /* Notice the percent sign before the apostrophe!! */

Sadly, we get the following error message when we run the program again:

ERROR: Literal contains unmatched quote.

==>BOB's<=='

ERROR: The macro DRUGPRINT will stop executing.

The problem is due to the %SCAN() function. When dealing with unbalanced quotation marks and/or parentheses, use %QSCAN() instead.

Macro Quoting – To %NRSTR Or Not to %NRSTR

Page 48: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%macro DrugPrint(DrugList=,thisDrugNbr=);

%put ==>%qscan(&DrugList.,&thisDrugNbr.)<==;

%mend DrugPrint;

%Let Drug1=SAMPLEX;

%Let Drug2=Samplex;

%Let Drug3=PULMICORT;

%Let Drug4=BOB%str(%’)s;

%DrugPrint(DrugList=%str(&Drug1.,&Drug2.,&Drug3.,&Drug4.),thisDrugNbr=4);

==>BOB's<==

When is another place where %STR(%’) may come in handy?

%Let BegDT=01JAN2006;

%Let EndDT=31DEC2006;

proc sql;

connect to oledb as SDIDW (init_string="…");

execute(

CREATE TABLE MYDATA AS

SELECT DATE_AUTHORIZED,COUNT(*) "SCRIPTS"

FROM BIGDATA

WHERE DATE_AUTHORIZED BETWEEN TO_DATE(%str(%’)&BegDT.%str(%’),’DDMONYYYY’)

AND TO_DATE(%str(%’)&EndDT.%str(%’),’DDMONYYYY’)

) by SDIDW;

quit;

This will allow the macro variables to resolve and you don’t have to put the quotes in your macro variables BegDT and EndDT.

Macro Quoting – To %NRSTR Or Not to %NRSTR

Page 49: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Note that:

%STR(%’) resolves to ’

%STR(%%) resolves to %

%STR(%)) resolves to )

%STR(%() resolves to (

There is much more to macro quoting than what I’ve mentioned here today. Refer to your SAS Macro Language manual, or dismiss this topic completely from your mind.

Macro Quoting – To %NRSTR Or Not to %NRSTR

Page 50: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com As we’ve seen already, you can use the CALL SYMPUT and SYMGET Data Step

functions to create a new SAS macro variable or read an existing SAS macro variable. The RESOLVE Data Step function is similar to the SYMGET function except

that it accepts a wider range of arguments allowing you to, say, call a SAS Macro.

The Data Step and Macros – RESOLVE and CALL EXECUTE

For example, suppose we want to compute the sine squared plus the cosine squared of a number:

%macro OnlyOneForMe(x=);

%sysevalf(%sysfunc(sin(&x.))*%sysfunc(sin(&x.)) + %sysfunc(cos(&x.))*%sysfunc(cos(&x.)))

%mend OnlyOneForMe;

data OneIsTheLoneliestNumber;

OneForTheRoad=resolve('%OnlyOneForMe(x=.5)');

run;

Notice that I am not setting the calculation in the macro OnlyOneForMe to a

variable, but am leaving it floating in space…and with no ending semi-colon!

Note that this seems like a great idea if you want to create your own function, but be aware of performance problems by continually calling a SAS Macro for each row in a million+ row dataset.

Page 51: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com The CALL EXECUTE Data Step function has two nice purposes. It can be

used to build SAS programs from within a Data Step. The SAS program you’ve built will be executed after the current Data Step completes.

The Data Step and Macros – RESOLVE and CALL EXECUTE

The other purpose is to run SAS macros from within a Data Step. In this case, the macro runs immediately and does not wait until the Data Step is completed.

Recall the SAS Macro PrintNums from above:

%macro PrintNums(N=);

%Let iter=1;

%do %while(&iter. le &N.);

%put ==>&iter.<==;

%Let iter=%eval(&iter. + 1);

%end;

%mend PrintNums;

Let’s use CALL EXECUTE to call this SAS macro several times. First, let’s create a

SAS Dataset with several rows:

data RowsOfNumbers;

num=1;output;

num=2;output;

num=3;output;

run;

Page 52: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Next, let’s call this SAS macro using CALL EXECUTE:

data _null_;

set RowsOfNumbers;

call execute('%PrintNums(N=' || left(num) || ')');

run;

The Data Step and Macros – RESOLVE and CALL EXECUTE

The results are:

==>1<==

==>1<==

==>2<==

==>1<==

==>2<==

==>3<==

Here is an example of how to create a SAS program using CALL EXECUTE:

data _null_;

set MyNDCs(keep=NDC_KEY);

call execute( "DATA NDC_" || NDC_KEY || ";" );

call execute( " SET MYRXDATA(WHERE=(NDC_KEY='" || NDC_KEY || "'));" );

call execute( "RUN;" );

run;

The Data Steps you see being constructed above will be run at the end of the DATA _NULL_.

Page 53: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Occasionally, you will need to enter a different number of arguments each time you call a SAS macro. While we don’t recommend this over entering your data within a specific parameter, you should be aware of this option.

PARMBUFF and SYSPBUFF

Instead of entering your parameters next to the macro name, you type /PARMBUFF

instead. The SAS Macro processor will takes all of the arguments entered in the call to your SAS macro and place them in a SAS Macro Variable called SYSPBUFF.

SYSPBUFF includes the separating commas.

%macro PrintNDCs/PARMBUFF;

%Let thisIter=1;

%Let thisNDC=%scan(&syspbuff.,&thisIter.);

%do %while(&thisNDC. ne );

%put ==>&thisNDC.<==;

%Let thisIter=%eval(&thisIter. + 1);

%Let thisNDC=%scan(&syspbuff.,&thisIter.);

%end;

%mend PrintNDCs;

%PrintNDCs(111,222,333)

%PrintNDCs(111,222,333,444)

%PrintNDCs(111,222,333,444,555)

Note that SYSPBUFF also includes the left and right parenthesis: (111,222,333)

The reason the %SCAN works is because the left paren, right paren and comma are

delimiters by default. Note that you can also use named parameters as well.

Page 54: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Macro variables can be either local or global in scope.

%Local vs. %Global Macro Variables

A global SAS Macro Variable can be used by (resolved within) any SAS Macro, Data Step or Proc Step. They exist for the entire job. %Let variables are global when

outside of a SAS Macro.

You define a global SAS Macro Variable by using the %global statement within

your SAS Macro followed by one or more space-delimited macro variable names:

%global gMacVar1 gMacVar2;

A local SAS Macro Variable can only been used within a specific SAS Macro. They exist only within a SAS Macro.

You define a local SAS Macro Variable by using the %local statement within your

SAS Macro followed by one or more space-delimited macro variable names:

%local myMacVar1 myMacVar2;

Examples of SAS Macro Variables which would make good candidates for being defined as local, are the macro variables thisIter, thisNDC, i, etc.

Both global and local macro variables defined using the %global and %local

statements initialize the variables to null (zero characters).

Be aware that you could unintentionally overwrite an existing global SAS Macro Variable within your SAS Macro program by using a local variable with the same name. This can be very hard to debug, so it’s prudent to use %local.

Page 55: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com As an example of this:

%Let bob=5; /* Defined outside a macro: global */

%put =>&bob.; /* 5 */

%macro doit;

%Let bob=1; /* No %local, so global */

%put ==>&bob.; /* 1 */

%mend doit;

%doit

%put ===>&bob.; /* 1 */

%Local vs. %Global Macro Variables

Compare this to:

%Let bob=5; /* Defined outside a macro: global */

%put =>&bob.; /* 5 */

%macro doit;

%local bob; /* bob is now local to this macro */

%Let bob=1;

%put ==>&bob.; /* 1 */

%mend doit;

%doit

%put ===>&bob.; /* 5 */

Page 56: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com There are several useful additional Automatic Macro Variables you can use to make your SAS Macro code more bulletproof. Here is an example using SYSFILRC, an Automatic SAS Macro Variable that returns a zero after a successful FILENAME statement is issued.

More Automatic Macro Variables – SYSFILRC, SYSLIBRC, etc.

%macro gzipsasds/parmbuff;

%local filelist thisfile indx userdir outdir waitdel flgstop iters itercap;

%global _prod;

%Let waitdel=N; /* Suspend until gzip.flag is deleted. */

%Let itercap=240; /* Iteration cap...240 fifteen second segments=1 hour */

%*---------------------------------------------------------------------------------*;

%* Create a macro variable of the user`s ready subdirectory. *;

%*---------------------------------------------------------------------------------*;

%if (%upcase(&_prod.) eq 192.168.111.222| %upcase(&_prod.) eq 192.168.111.333) %then %do;

proc sql noprint;

select trim(left("H:\Data\" || trim(left(dirname)))),trim(left("H:\Data\" || trim(left(dirname)) ||

"\ready"))

into :outdir,:userdir

from PROD.EGuserlist

where upcase(userid)=upcase("&_prod.");

quit;

%end;

%else %do;

Page 57: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

More Automatic Macro Variables – SYSFILRC, SYSLIBRC, etc.

proc sql noprint;

select trim(left("H:\Data\" || trim(left(dirname)))),trim(left("H:\Data\" || trim(left(dirname)) ||

"\ready"))

into :outdir,:userdir

from PROD.EGuserlist

where upcase(userid)=upcase("&sysuserid.");

quit;

%end;

%*---------------------------------------------------------------------------------*;

%* Assign _REDYDIR to this user`s ready subdirectory. *;

%*---------------------------------------------------------------------------------*;

filename _REDYDIR "&userdir.";

run;

%*---------------------------------------------------------------------------------*;

%* Check if the READY subdirectory exists. *;

%*---------------------------------------------------------------------------------*;

%if (&sysfilrc. eq 0) %then %do;

%*---------------------------------------------------------------------------------*;

%* Check if the user passed no parameters. *;

%*---------------------------------------------------------------------------------*;

%if (&syspbuff. ~= ()) & (&syspbuff. ~= ) %then %do;

%*---------------------------------------------------------------------------------*;

%* Get the list of files to compress from the macro call line. *;

%*---------------------------------------------------------------------------------*;

%Let filelist=%nrbquote(%substr(&syspbuff.,2,%length(&syspbuff.)-2));

%Let indx=1;

Page 58: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

More Automatic Macro Variables – SYSFILRC, SYSLIBRC, etc. %*---------------------------------------------------------------------------------*;

%* For each file, add it to the gzip.flag file in the user`s /ready directory. *;

%*---------------------------------------------------------------------------------*;

%do %while(%scan(&filelist.,&indx.,%str(,)) ~= );

%*---------------------------------------------------------------------------------*;

%* Get the next file from the list of files to compress. *;

%*---------------------------------------------------------------------------------*;

%Let thisfile=%scan(&filelist.,&indx.,%str(,));

%*---------------------------------------------------------------------------------*;

%* If the 1st file is a W, then the user wants to wait until gzip.flag is deleted. *;

%*---------------------------------------------------------------------------------*;

%if (&indx. eq 1) & %nrbquote(%upcase(&thisfile.)) eq (%nrbquote(W)) %then %do;

%Let waitdel=Y;

%Let indx=%eval(&indx. + 1);

%end;

%else %do;

%*---------------------------------------------------------------------------------*;

%* Write this file out the gzip.flag appending when necessary. *;

%*---------------------------------------------------------------------------------*;

data _null_;

file _REDYDIR("gzip.flag") %if &indx. ne 1 %then %do;

mod

%end;

;

if index("&thisfile.",".sas7bdat") > 0 then do;

put @1 "%trim(&outdir.)\&thisfile.";

end;

else do;

put @1 "%trim(&outdir.)\&thisfile..sas7bdat";

end;

run;

Page 59: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

More Automatic Macro Variables – SYSFILRC, SYSLIBRC, etc.

%Let indx=%eval(&indx. + 1);

%end;

%end;

filename _REDYDIR "&userdir.";

run;

%*---------------------------------------------------------------------------------*;

%* If the user has requested to wait until the gzip.flag file has been deleted, *;

%* then run the following code below. *;

%*---------------------------------------------------------------------------------*;

%if &waitdel. eq Y %then %do;

%Let flgstop=N;

%Let iters=0;

%do %while( (&flgstop eq N) & (&iters <= &itercap.) );

filename _REDYFIL "%trim(&userdir.)\gzip.flag";

run;

%if (&sysfilrc. eq 0) %then %do;

filename _REDYFIL clear;

run;

%Let iters=%eval(&iters. + 1); /* increment iters */

%Let rc=%sysfunc(sleep(15,1)); /* Sleep for 15 seconds */

%end;

%else %do;

Page 60: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

More Automatic Macro Variables – SYSFILRC, SYSLIBRC, etc.

filename _REDYFIL clear;

run;

%Let flgstop=Y;

%end;

%end;

%end;

%end;

%else %do;

%put *-------------------------------------------------------------------*;

%put * MUST SPECIFY PARAMETERS WHEN CALLING MACRO GZIPFILES. *;

%put *-------------------------------------------------------------------*;

%end;

%end;

%else %do;

%put *-------------------------------------------------------------------*;

%put * YOUR READY SUBDIRECTORY DOES NOT EXIST! PLEASE CREATE ONE! *;

%put *-------------------------------------------------------------------*;

%end;

%mend gzipsasds;

%gzipsasds(W,practitioner_month);

You can do the same this for a LIBNAME statement, by using the SYSLIBRC

Automatic SAS Macro Variable.

Page 61: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com There are other Automatic Macro Variables that you might find useful:

SYSDSN – contains the libref and name of the most recently created dataset.

SYSENV – Returns FORE if the program is running in SAS DM; otherwise, BACK.

SYSERR – returns an error code set by some SAS procedures and the Data Step

SYSMACRONAME – returns the name of the running SAS Macro

SYSNCPU – returns the number of CPUs on the machine where SAS is running

SYSSCP – returns the name of the Operating System (e.g., WIN)

SYSSCPL – returns a more descriptive name of the Operating System (e.g., WIN_NTSV)

SYSUSERID – the userid or the current running SAS process

SYSVER – returns the SAS System version number (e.g., 9.1)

SYSVLONG – returns the SAS System long version number (e.g., 9.01.01M3P020206)

…and so many more…

More Automatic Macro Variables – SYSFILRC, SYSLIBRC, etc.

Page 62: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com You’re hooked! You’ve tasted the cheesy goodness of SAS Macros, you’ve created several SAS macros, and you want to share them with your co-workers. Excellent!

There are three ways to share your SAS Macros:

1. Use %INCLUDE to include the SAS Macro code into a running SAS job

2. Use the SASAUTOS System Option to point to a location containing your SAS Macros

3. E-Mail your SAS Macro code to everyone…probably not the best option.

Example of %INCLUDE:

%include "C:\MyStuff\Bob\BigMac.sas";

Example of SASAUTOS:

options sasautos=(sasautos,"C:\MyStuff\Bob\");

/* To call your macro, just do this… */

%BigMac(parm1=5,parm2=6)

Note that your macro must be the SAME name as the file it is in. BigMac() is stored

in BigMac.sas. Note that your SAS System Administrator may have already set up a

network location for you to place your SAS macros. Check with him/her before creating your own.

Sharing Your SAS Macro Code with the Down-Trodden Masses

Page 63: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com Please see the three handouts:

1. BinaryAllCombos.sas

2. GetDataTypes.sas

3. GenerateLAB.sas

Example dataset produced from BinaryAllCombos.sas:

Obs A B C D _TOTVARS

1 0 0 0 0 0

2 0 0 0 1 1

3 0 0 1 0 1

4 0 0 1 1 2

5 0 1 0 0 1

6 0 1 0 1 2

7 0 1 1 0 2

8 0 1 1 1 3

9 1 0 0 0 1

10 1 0 0 1 2

11 1 0 1 0 2

12 1 0 1 1 3

13 1 1 0 0 2

14 1 1 0 1 3

15 1 1 1 0 3

16 1 1 1 1 4

Examples of SAS Macro Code

Page 64: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

*----------------------------------------------------------------------------*;

* Macro: GetDataTypes *;

* Purpose: This macro creates a series of global SAS macro variables holding *;

* the name of the requested variable and its associated data type. *;

* An incoming SAS dataset is used to determine the datatypes but *;

* only one row is pulled in. *;

* The global macro variables start with the characters you specify *;

* in the parameter MVAR, but the program adds an N for the name and *;

* a T for the type to the end of the macro variable name. That is, *;

* if you specify MVAR=V, then VN1 holds the first variable name and *;

* VT1 holds the first variable type. Note that VTOT hold the number*;

* of total variables entered in the VARS parameter. *;

*----------------------------------------------------------------------------*;

%macro GetDataTypes(vars=,mvar=,inds=);

%global &mvar.TOT;

%local totvars var0 i thisvar;

%Let &mvar.TOT=0;

%*----------------------------------------------------------------------*;

%* Parse the VARS parameter and put into separate local macro variables.*;

%*----------------------------------------------------------------------*;

%Let var0=0;

%Let i=1;

%Let thisvar=%scan(&vars.,&i.,%str( ));

%do %while(&thisvar. ne );

%local var&i.;

%global &mvar.N&i. &mvar.T&i.;

%Let var&i.=&thisvar.;

%Let i=%eval(&i.+1);

%Let thisvar=%scan(&vars.,&i.,%str( ));

%end;

%Let var0=%eval(&i.-1);

Examples of SAS Macro Code

Page 65: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%*----------------------------------------------------------------------*;

%* Pull in the first row of data in order to determine the data types. *;

%*----------------------------------------------------------------------*;

data _null_;

set &inds.(obs=1);

%do i=1 %to &var0.;

call symput("&mvar.N&i.","&&var&i.");

call symput("&mvar.T&i.",vtype(&&var&i.));

%end;

run;

%Let &mvar.TOT=&var0.;

%*----------------------------------------------------------------------*;

%* Print out the results. *;

%*----------------------------------------------------------------------*;

%do i=1 %to &var0.;

%put &&VN&i. &&VT&i.;

%end;

%mend GetDataTypes;

Examples of SAS Macro Code

Page 66: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com *----------------------------------------------------------------------------*;

* Macro: BinaryAllCombos *;

* Purpose: This macro creates a dataset containing all binary combinations *;

* of the requested variables. That is, if you enter three variables*;

* in the VARS parameter, you will be back the output dataset with *;

* 8 total rows and three variables each containing a zero or a one. *;

*----------------------------------------------------------------------------*;

%macro BinaryAllCombos(vars=,outds=);

%local totvars var0 i thisvar;

%*----------------------------------------------------------------------*;

%* Parse the VARS parameter and put into separate local macro variables.*;

%*----------------------------------------------------------------------*;

%Let var0=0;

%Let i=1;

%Let thisvar=%scan(&vars.,&i.,%str( ));

%do %while(&thisvar. ne );

%local var&i.;

%Let var&i.=&thisvar.;

%Let i=%eval(&i.+1);

%Let thisvar=%scan(&vars.,&i.,%str( ));

%end;

%Let var0=%eval(&i.-1);

%if &var0. >= 1 %then %do;

%*----------------------------------------------------------------------*;

%* Use PROC PLAN to create the outgoing dataset. This procedure does *;

%* not allow for zero starting values. *;

%*----------------------------------------------------------------------*;

Examples of SAS Macro Code

Page 67: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com proc plan;

factors

%do i=1 %to &var0.;

&&var&i.=2 comb

%end;

/noprint;

output out=&outds.;

run;

%*----------------------------------------------------------------------*;

%* Subtract one from each variable so that the variables contain only *;

%* zeros and ones. *;

%*----------------------------------------------------------------------*;

data &outds.;

set &outds.;

%do i=1 %to &var0.;

&&var&i.=&&var&i. - 1;

%end;

_TOTVARS=sum(

%do i=1 %to &var0.;

&&var&i.

%if &i. ne &var0. %then %do;

,

%end;

%end;

);

run;

%end;

%else %do;

Examples of SAS Macro Code

Page 68: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

%put *-------------------------------------------------------------*;

%put * ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR *;

%put *=============================================================*;

%put * YOU MUST SPECIFY AT LEAST ONE VARIABLE FOR THE VARS PARAM. *;

%put *-------------------------------------------------------------*;

%end;

%mend BinaryAllCombos;

Examples of SAS Macro Code

Page 69: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com *----------------------------------------------------------------------------*;

* Macro: GenerateLAB *;

* Purpose: This macro generates the appropriate SQL code for use with PROC *;

* SQL to compute the min and max ranges for the lab data. *;

*----------------------------------------------------------------------------*;

%macro GenerateLAB(CountVar=,ginds=,goutds=,nfvars=,timevar=,addlvars=);

%*----------------------------------------------------------------------------*;

%* Create all binary combinations of those variables that will be have the *;

%* No Filter option in the drop-down box. *;

%*----------------------------------------------------------------------------*;

%BinaryAllCombos(vars=&nfvars.,outds=AllCombos);

%*----------------------------------------------------------------------------*;

%* Create a series of SAS macro variables containing the data type (N=numeric,*;

%* and C=character) for all of the No Filter variables. The INDS parameter *;

%* is used to determine the datatype. *;

%* VTOT holds the total number of variables in mNFVARS. *;

%* VN1 to VN6 holds the names of the variable. *;

%* VT1 to VT6 holds the data type of the variable(C=char,N=numeric). *;

%*----------------------------------------------------------------------------*;

%GetDataTypes(vars=&nfvars.,mvar=V,inds=&ginds.);

%*----------------------------------------------------------------------------*;

%* Determine the total number of records in AllCombos. *;

%*----------------------------------------------------------------------------*;

proc sql noprint;

select nobs

into :accnt

from dictionary.tables

where libname="WORK"

and memname="ALLCOMBOS";

quit;

Examples of SAS Macro Code

Page 70: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com %*----------------------------------------------------------------------------*;

%* For all rows, create macro variables for each column in AllCombos. *;

%* Produces VZr_c where r is the row number and c is the column number. *;

%*----------------------------------------------------------------------------*;

proc sort data=AllCombos;

by descending _TOTVARS;

run;

data _null_;

length strVarName $ 30;

set AllCombos;

%do k=1 %to &VTOT.;

strVarName=compress("VZ" || left(_n_) || "_&k.");

call symput(strVarName,&&VN&k.);

%end;

run;

%*----------------------------------------------------------------------------*;

%* Generate the PROC SQL statements based on AllCombos and the datatypes. *;

%*----------------------------------------------------------------------------*;

proc sql noprint;

%do r=1 %to &accnt.;

%if &r. eq 1 %then %do;

DROP TABLE &goutds.;

CREATE TABLE &goutds. AS

%end;

%else %do;

INSERT INTO &goutds.

%end;

Examples of SAS Macro Code

Page 71: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com %Let mGB=;

SELECT

%do c=1 %to &VTOT.;

%if &&VZ&r._&c.=0 %then %do;

%if &&VT&c.=C %then %do;

" " AS &&VN&c.,

%end;

%else %if &&VT&c.=N %then %do;

. AS &&VN&c.,

%end;

%end;

%else %if &&VZ&r._&c.=1 %then %do;

&&VN&c.,

%Let mGB=&mGB &&VN&c;

%end;

%end; %* end of c *;

&addlvars.,MIN(&CountVar.) AS MIN_VALUE,MAX(&CountVar.) AS MAX_VALUE,COUNT(*) AS ROWCNT,SUM(&CountVar.) AS

SUM_VALUE

FROM &ginds.

WHERE &timevar.>0

%if &r. ne &accnt. %then %do;

GROUP BY %sysfunc(translate(&mGB,","," ")),&addlvars.

%end;

%else %if &r. eq &accnt. %then %do;

GROUP BY &addlvars.

%end;

Examples of SAS Macro Code

Page 72: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com ;

%end; %* end of r *;

;

quit;

proc datasets library=work nolist force;

delete AllCombos;

run;

quit;

%mend GenerateLAB;

%GenerateLAB(CountVar=CD4,

ginds=SASIO.INCOMING_DATA,

goutds=OUTGOING_DATA,

nfvars=&mNFVARS.,

timevar=C_DATE,

addlvars=%nrbquote(C_DATE));

Examples of SAS Macro Code

Page 73: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com Copyright ©2011 sheepsqueezers.com

sheepsqueezers.com

DON’T GO MACRO CRAZY! It’s very easy for

someone new to SAS Macros to decide to macro-

tize EVERYTHING! DON’T DO THAT! Use SAS

Macros where appropriate and legal in your state!

Final Words

Page 74: SAS Lecture Series SASMacros - sheepsqueezers.comsheepsqueezers.com/media/presentations/SAS_Lecture_Series_SAS… · you to associate a SAS macro variable with the text of your choice:

sheepsqueezers.com

Copyright ©2011 sheepsqueezers.com

Support sheepsqueezers.com If you found this information helpful, please consider

supporting sheepsqueezers.com. There are several

ways to support our site:

Buy me a cup of coffee by clicking on the

following link and donate to my PayPal

account: Buy Me A Cup Of Coffee?.

Visit my Amazon.com Wish list at the following

link and purchase an item:

http://amzn.com/w/3OBK1K4EIWIR6

Please let me know if this document was useful by e-mailing me at [email protected].