/* The macro facility is a tool that can help you automate repetitive tasks and reduce the amount of time and text necessary to do these tasks. The macro facility consists of the macro processor and the macro language. It is a "pre-processor" that resolves the commands of the macro language into SAS statements. It does not read data or perform any procedures on data. The result of every macro is SAS statements. The macro language consists of macro variables (beginning with the ampersand &) and macro names and statements (beginning with the percent sign %). Using macro variables is a convenient way to perform text substitution. An example of this follows. */ %LET trees = trees02; /* Definition of macro variable does not include the &, but when referenced in SAS code, it does. */ libname sasdata "Z:\public_html\stat295\datasets"; proc print data=sasdata.&trees; title "Macro variable example - data set &trees"; run; /* Macro variables can be assigned in a %LET statement, as above. Anywhere the macro variable appears, its value is substituted into the SAS statement in place of the macro variable name. Note what happens in the title when we use single quotes instead of double quotes. */ proc print data=sasdata.&trees; title 'Macro variable example - data set &trees'; title2 'Macro variable not resolved inside single quotes'; run; /* So, if you want a macro variable resolved into its value inside something that is quoted, you must use double quotes. Using single quotes, the macro variable resolution does not occur. Macro variables can be used in open code, outside of a macro definition. To perform more complex tasks, it is necessary to define a macro. Macros begin with a %MACRO macro_name; statement and end with a %MEND macro_name; statement. */ %MACRO stats; title "Descriptive statistics of &dep_var by &by_var in data set &trees"; proc sort data=sasdata.&trees; by &by_var; run; proc means; by &by_var; var &dep_var; run; %MEND stats; /* Running the above code creates the macro "stats" but nothing actually happens. To make something happen, define values for the macro variables referenced in the macro and "call" the macro. */ %LET trees = trees02; %LET by_var = treatment; %LET dep_var = dbh; %stats /* The macro stats uses two macro variables, whose values are substituted in the appropriate places to perform descriptive statistics. The macro is "called" by placing a % in front of its name. Note that no semi-colon is used at the end of the statement. This is perhaps the only instance in the entire SAS language where a semi-colon is not needed. Instead of using %LET statements to define macro variables, we can define them as macro parameters along with the definition of the macro in the %MACRO statement. Values of the macro parameters (variables) are given when the macro is called. */ %MACRO stats (trees= ,by_var= ,dep_var= ); title "Descriptive statistics of &dep_var by &by_var in data set &trees"; proc sort data=sasdata.&trees; by &by_var; run; proc means; by &by_var; var &dep_var; run; %MEND stats; /* This makes it easier to run macros without first assigning values to macro variables. You pass them into the macro as parameters when calling the macro. You can then repeatedly call the macro with different parameter values. */ %stats (trees=trees02, by_var=treatment, dep_var=dbh) %stats (trees=trees04, by_var=treatment, dep_var=dbh) %stats (trees=trees0204, by_var=treatment, dep_var=dbh02 dbh04) /* This is an example of using keyword parameters in macro definitions. When you call the macro, you must give the keyword (macro variable name) along with an = sign and a value. The keywords can be given in any order. It is also possible to provide default values for any or all keywords when the macro is defined. */ %MACRO stats (trees=trees02 ,by_var= ,dep_var=dbh); title "Descriptive statistics of &dep_var by &by_var in data set &trees"; proc sort data=sasdata.&trees; by &by_var; run; proc means; by &by_var; var &dep_var; run; %MEND stats; %stats (by_var=treatment) %stats (trees=trees04, by_var=treatment) %stats (trees=trees0204, by_var=treatment, dep_var=dbh02 dbh04) /* You can also pass parameters into a macro using positional parameters. This means that the parameters must be referenced when the macro is called in the same order as they are given on the %MACRO statement. With positional parameters, it is not possible to supply default values. Note the importance of commas in the %MACRO statement and when the macro is called. */ %MACRO stats (trees, by_var, dep_var); title "Descriptive statistics of &dep_var by &by_var in data set &trees"; proc sort data=sasdata.&trees; by &by_var; run; proc means; by &by_var; var &dep_var; run; %MEND stats; %stats (trees02, treatment, dbh) %stats (trees04, treatment, dbh) %stats (trees0204, treatment, dbh02 dbh04) /* Notice that in the SAS log, the only thing that appears when a macro is called are the NOTEs and the macro call itself. On those very rare occasions when you make an error (ha, ha), it is difficult to figure out where the error has occurred, because the SAS statements resulting from the macro call are not echoed back into the log. Note the results in the log when an error is purposely made. */ %MACRO stats (trees, by_var, dep_var); title "Descriptive statistics of &dep_var by &by_var in data set &trees"; proc sort data=sasdata.&trees; by &by_var; run; proc means; by &by_var; var &dep_vars; run; %MEND stats; %stats (trees0204, treatment, dbh) /* Fortunately, there are several system options pertaining to macros that help us with debugging. The two most useful ones are probably the SYMBOLGEN and MPRINT options. SYMBOLGEN prints a line in the log that tells you how each macro variable has been resolved. MPRINT echoes back into the log all the SAS statements resulting from the call of the macro. Let's also turn on the SPOOL option as suggested. */ ; options symbolgen mprint spool; %stats (trees0204, treatment, dbh) /* Let's rerun the macro definition after fixing the error and call it again. */ %MACRO stats (trees, by_var, dep_var); title "Descriptive statistics of &dep_var by &by_var in data set &trees"; proc sort data=sasdata.&trees; by &by_var; run; proc means; by &by_var; var &dep_var; run; %MEND stats; %stats (trees0204, treatment, dbh) /* Let's fix the error in the macro call and rerun. */ %stats (trees0204, treatment, dbh02 dbh04) /* These options are useful for debugging. However, they should not be used all the time, especially if you are doing something like bootstrapping or simulations where a macro or a procedure may be run 10,000 times. The log would fill up your hard drive and SAS would interrupt its execution and ask you to resolve this problem somehow. It is even possible for the NOTEs in the log to cause this kind of problem, so when running macros that perform something thousands of times, you can turn off the NOTEs also. */ ; options nosymbolgen nomprint nospool nonotes; %stats (trees0204, treatment, dbh02 dbh04) /* The macro language consists of statements, functions, and automatic macro variables. The entire macro language reference can be found in the SAS help under "SAS Products" -> "Base SAS" -> "SAS Macro Reference". */