CHAPTER 9 - SAS MACRO PROCESSING I. INTRODUCTION II. Process III. Macro Facility Overview A. Components of Macro Facility B. Macro Language Components C. Macro Definitions and Referencing D. Referencing Environment: global or local E. Programming Statements F. Functions G. AutoCall Facility H. System Options INTRODUCTION This chapter provides a brief introduction to the macro facility in BASE SAS and demonstrates a few of its many features. Most of the techniques described here are based on information found in SAS BASICS users guide, the SAS Macro Facility Guide, and the experiences gleaned from actual programs. A detailed reference to the Macro Language is Art Carpenter's "Complete Guide..." which is guaranteed to lead you through the twists and turns of macros and then exit in a straight path. When should macros be used in SAS programs? Experience is usually the best guide to determine when a macro will provide a more elegant and efficient solution than brute force coding. However, one can first apply the wall-paper test: if the present or anticipated code looks like wall paper (that is lots of commands or PROCS that are repeated or many statements containing changing index numbers) then the program is probably a good candidate to be designed and written with one or more macros. Macro variables are also helpful when the same analysis is to be applied to different variables or when single numbers calculated from a procedure or data step inside the program need to be passed on to a subsequent step, (e.g., the number of observations or the median of a variable in a data set). SAS Processes To understand how a SAS macro works, first consider how SAS processes a block of statements. When SAS executes a program, all statements are read into the input stack, and passed through the SAS supervisor one token at a time. Tokens are strings separated by blanks or operators. The SAS supervisor reads tokens until it receives a semi-colon, which completes a SAS statement. Once the supervisor reads a complete statement, it is checked for syntax, and the statement is passed to the word scanner section of the supervisor. Here, the tokens are examined for their value, i.e. if the token is a SAS reserve word, user name and type, and passes the tokens on to the compiler. This process continues until a step boundary word is read. Step boundary keywords are DATA, PROC, RUN, QUIT, ENDSAS, and CARDS (and its other formats). Then the SAS compiler compiles the code and executes statements for that step. Only one step is compiled and executed independently. Macro compilation and execution are separate processes from DATA or PROC compilation and execution. Understanding the difference will help you to understand macro expression evaluations and how to make SAS work better for you. III. Macro Facility Overview: When would one use a macro? The SAS Macro Facility allows you to perform tasks that would be tedious or even impossible without it. For use in batch mode processing, SAS Macro Facility will allow you to: * retrieve system information from the SAS Supervisor * perform conditional execution of SAS DATA and PROC steps * generate data-dependent SAS statements (SAS Code) * communicate information between SAS steps * invoke repetitive SAS code The Macro Facility is a tool for extending and customizing the SAS system and reducing the amount of SAS statements you must enter to do repetitive tasks. The Facility allows you to package small or large amounts of text into units or modules that have assigned names. Once they are defined, you work with the names rather than the text itself. When you use a Macro Facility name in a SAS program, the Macro Facility generates SAS statements and commands as needed. The rest of the SAS system uses those statements and commands just like the ones you enter. A. Components of Macro Facility There are two components in the Macro Facility: * The macro processor is the portion of SAS that does the work. * The macro language is the language used to communicate with the macro processor The macro language has variables, program statements, expressions, and functions - the same pieces that make up the SAS DATA step language. However, the Macro language uses the patterns %name and &strng to trigger Macro processing activities. B. Macro Language Components The components of the Macro Language are: * macro variables * macro statements * macro functions * macro expressions & constant text Macro variables (or symbolic variables) are different from DATA step variables and can be defined anywhere in a SAS job, except after a CARDS, CARDS4, DATALINES, PARMCARDS, or PARMCARDS4 statement. They are global in the sense that they are available throughout the program. Whereas a DATA step variable name is limited to use within that step, and must be carried forward within a SAS dataset to be used in a subsequent step, a macro variable value remains constant until it is changed or the SAS session ends. C. Macro Definitions and Referencing How to Assign Values to Macro Variables Macro or global variables can be used throughout a SAS program across multiple DATA and PROC steps. The easiest way to assign a value to a macro variable is the %LET statement. This is an effective approach when you have variable names for which the same analysis is to be performed on separate runs or you want to change the value of a numerical constant. The content of a macro variable may either be a number, one or more variable names, or a series of words with spaces as the need demands. For example, if you want to set the value of a numerical constant, you can assign it to a macro variable: %LET cpi=1.2 ; To adjust data by the current value of a variable by the Consumer Price Index, enter the value of cpi=1.2 once and then enter the macro variable as you subsequently access several different DATA steps to adjust variables as needed. The value of cpi you enter is used in subsequent DATA or PROC steps by placing a & before the macro variable name: &cpi. Whenever you see &cpi in a program it is as if you had typed 1.2 at that point. This approach is especially useful if the value of cpi were to appear many times within a program and you want to perform sensitivity testing by allowing it to assume other values. To place the contents of the macro variable within TITLE or LABEL statement, you will need to use double quotes (") rather than single quotes (') to enclose the text. DATA new; SET ; LABEL inc_adj="adjusted income"; inc_adj = &cpi. * income_1975; PROC PRINT noobs; VAR inc_adj income_1975 ; TITLE "Income adjusted for inflation with CPI = &cpi."; RUN; If you have several variable names that you want to analyze with the same program, you can directly insert them one at a time into separate macro variables: %LET y=income; %LET x=age; %LET statements are placed outside the DATA or PROC steps and define numbers or characters to a macro variable name. The value for a macro variable is every character, including spaces and quotes, to the right of the equals sign up to, but not including, the semicolon. In the %LET statements listed above, y is the name of a macro variable (referred to subsequently as &y) and it represents income; x is a second macro variable (referred to as &x) and represents the variable age. What makes macro variables so helpful is these names only need to be placed in statements once rather than the actual variable name. You only need to change the macro variable definition. Summary statistics may need to be calculated within the command file to be passed onto subsequent DATA or PROC steps and thus you will not know their values before the file is run. CALL SYMPUT within a DATA step allows you to pass such information into macro variables, such as the number of observations in a dataset, a mean, median, or other summary statistic of a variable, or a number calculated from of a collection of variables, which is placed into a macro variable and then passed on to a subsequent DATA or PROC step. The value of a summary statistic can be assigned to the contents of a macro variable via CALL SYMPUT in a regular or _null_ DATA step, and then resolved in a subsequent DATA or PROC steps. For example: DATA _null_; SET mydat Nobs=nn; CALL SYMPUT("nobs",nn); STOP; RUN; The macro variable &nobs contains the count of the number of observations in the SAS data set called mydat. To reference income, age, or nobs in the program, place an "&" in front of its associated macro variable name, i.e., &y (wherever you would enter income) or &x (wherever you would enter age), or &nobs (whenever you would enter the number of observations). The notation &y, &x, or &nobs is called a "macro variable references". After creation of macro variables, the reference is resolved by the macro processor using &y, &x, or &nobs. To change the macro variables all you need to do is edit the %LET definitions of the macro variable names. For example, %LET y=height; %LET x=weight; will overwrite the macro variable y with the value height and x with the value weight. To delete a macro variable from memory (beginning with Version 8.2), enter the %SYMDEL command. It can be placed within a macro or in open code. %LET test = xxxxx; %PUT test; %SYMDEL test; %PUT test; To delete all global macros: * determine the names of macros with GLOBAL designation; DATA MVrs ; SET sashelp.vmacro ; Where Scope = 'GLOBAL' ; run ; PROC PRINT; run; * delete the ones you need; DATA _null_ ; SET MVrs ; CALL SYMDEL( Name ) ; RUN; Delete all user-defined macro variables from the global symbol table: %MACRO delvars; DATA del_vars; SET sashelp.vmacro; run; data _null_; SET del_vars; IF scope='GLOBAL' then call execute('%symdel '||trim(left(name))||';'); run; %mend; %delvars Assume you have a data set with three variables called age, education, and occupation and you want to insert all three of them in several VAR or MODEL statements (as X values) throughout a program. To place all three variables into one macro variable use: %LET xvar=age education occupation; Enter the macro variable &xvar anywhere in the program you want to use all three variables separated by spaces in the same statement: PROC PRINT DATA=gss; VAR id income &xvar; RUN; is the same code as PROC PRINT DATA=gss; VAR id income age education occupation; RUN; The %LET statement can also create a macro variable that contains multiple statements found in a SAS program: %LET plot=%STR(PROC PLOT; PLOT income*age; PROC PRINT income age;); In this case, the complete value of the macro variable is enclosed in the %STR macro function so that the semicolons within the value are part of the desired TEXT and do not specify the end of the %LET statement. The simplest type of macro works much like this macro variable just demonstrated. It uses the same concepts of writing a subroutine in a programming language. Complex code can be inserted into the macro; in fact, that is what makes them so useful. SAS %MACROs can do many things that macro variables cannot. A macro is the collection of all statements that are inserted between the %MACRO; and %MEND; statements. The structure of the macro between these two statements is basically whatever is needed to get the job done: %MACRO (dataset,var1,var2,..); < insert SAS statements to be performed within macro > %MEND ; The %MACRO statement contains a name for the macro (lowercase == your choice for name) and . The macro ends with the %MEND; statement which should also include the macro name, very useful for editing or documenting code. The previous %LET statement shows how to create several statements as one macro variable. For long sections of code this approach is not very practical. The %MACRO and associated %MEND statements serve this very same purpose much more effectively. Here is a very simple macro to print and plot two variables: %LET dsn=mydata; %MACRO plot; %* print and plot y by x; PROC PRINT DATA=&dsn; VAR id &y &x; RUN; PROC PLOT DATA=&dsn; PLOT &y*&x='+'; RUN; %MEND plot; %plot RUN; To call a macro, place a "%" in front of its macro_name in the SAS program. As used here, %plot is called a "macro invocation" or a "macro call". After defining the macro, the call is resolved by the macro processor by replacing the macro name with the text between the %MACRO and %MEND statements. Note that the macro call is not a SAS statement (so there is no need for a semicolon). The call assumes you have already defined the respective macro with a %MACRO statement and macro variables using %LET statements (or created in a DATA step or passed within the parentheses on the call statement). The statements in the macro must either appear prior to its first invocation within the SAS program, or stored as an external file and inserted into the program with an %INCLUDE statement prior to the macro call. If the macro is lengthy, it may be more effective to store it as an external file with a filename such as plot.mac and then insert it into the SAS program with an %INCLUDE statement at an appropriate location as shown next: OPTIONS ls=78 NOcenter; TITLE 'Demonstration of a simple macro program'; LIBNAME dat '.'; %LET y=income; %LET x=age; %LET dsn=gss; %INCLUDE 'c:\sas\macros\plot.mac'; * the %INCLUDE statement inserts the contents of the file plot.mac at this point in the program; DATA gss; SET dat.gss; RUN; %plot ; Note that %INCLUDE is SAS instruction to be executed during macro execution time when the code is generated. Hence %INCLUDE files cannot contain macro code that requires macro compilation. Another way to pass SAS macro parameters is through parentheses within the %MACRO statement. For example, you can write a macro passing two parameters: %MACRO mydata(mydata, myin); DATA &mydata; SET &myin; < insert SAS statements>; RUN; %MEND mydata; Then you can send the following statement: %mydata(design1, indata) and your SAS program, passing these parameters, will read like this: DATA design1; SET indata; < SAS statements>; RUN; In addition to using %LET statements to define macro variables you can pass along data set names, variable names, and other parameters within the parenthesis following the name in the %MACRO statement. For example, as in the previous example, if you have a data set called gss with income and age as variables, you can define the macro as: %MACRO plot(dsn,y,x); PROC PRINT DATA=&dsn; VAR id &y &x; RUN; PROC PLOT DATA=&dsn; PLOT &y*&x='+'; RUN; %MEND plot; * call the macro with the data set name and variables to be processed; %plot(gss,income,age) Now suppose you want to change the variable names to plot, say height x weight. Enter new names of the variables to be plotted with Macro variable references, %plot(newdata,height,weight) In many cases, it becomes inconvenient to allow yourself the option to redefine macro variables using %LET statements. To do this you can define the macro variables as part of the %MACRO statement. Two choices exist for this option: positional or keyword parameters. The following example illustrates both styles: Positional Parameters %MACRO plot(datin, x, y); PROC PLOT DATA=&datin; PLOT &y * &x; RUN; %MEND plot; call- %plot(mydat,income,age) Note that the macro call command must use the same order of x and y values that is found in the %MACRO statement. This one line command has the same result found if you had redefined &x and &y with %LET statements: %LET datin=mydat; %LET x=income; %LET y=age; %plot Keyword Parameters Keyword Parameters work very much like positional parameters of the %MACRO statement: %MACRO plot(datin=,yvar=,xvar=); PROC PLOT DATA=&datin; PLOT &yvar*&xvar; RUN; %MEND plot; %plot(datin=mydat,yvar=income,xvar=age) However, Keyword Parameters are often preferred to Positional Parameters because variables defined on the %MACRO statement can be assigned default values after the - sign such as: %MACRO plot(datin=mydata,yvar=income,xvar=age); PROC PLOT DATA=&datin; PLOT &yvar*&xvar; %MEND plot; %plot %plot(yvar=savings) %plot(yvar=retired_income,xvar=yrs_worked,dsn=newdata) RUN; Three calls to the %plot macro are issued in this example. If a specific parameter is not sent from the macro call (the %plot() command), then the default values listed in the %MACRO statement are used. The first call, %plot, produces a plot for income by age (the default values). The second call makes a plot of the desired value of yvar (savings) by the default value (age). In both calls the default data set, mydata, is used. Also, notice that with keyword parameters, the order of the variables listed is not important. The third call uses a completely different data set and new variable names in a different order presented in the %MACRO statement. %plot(yvar=income,xvar=age) %plot(xvar=age,yvar=income) That is, both macro invocations use data set called mydata and plot &yvar*&xvar or income*age. D. Referencing Environment: global or local When the system option MACRO is in effect, SAS programs have one or more referencing environments: a referencing environment is the area in which variable is available for use. Referencing environments are important because they determine whether the MACRO processor can locate a Macro variable that is referenced. The two types of referencing environments are "GLOBAL" and "LOCAL". The GLOBAL environment is the entire SAS program, while LOCAL environments are defined within Macros. The Macro processor uses referencing environments according to the following rules: 1) When executing Macro program statements that can create Macro variables, the Macro processor attempts to change the value of an existing Macro variable regardless of environment, rather than creating a new Macro variable. 2) When executing Macro program statements that can create Macro variables, and no Macro variable of the name requested exists, the Macro processor creates a variable in the current environment. 3) The %GLOBAL statement causes the Macro processor to create a variable in the global environment, regardless of the current environment. 4) The %LOCAL statement and Macro parameter creates Macro variable in the current local environment even if a variable of that name exists in another environment. E. Programming Statements Program statements for the Macro Language can be described as "open code" and "closed code" statements. Open code statements are used outside any definition as well as inside. Closed code can only be used inside a Macro definition. All previously discussed Macro statements are open code statements. Others include %CMS, %INPUT, %PUT, %TSO, and all Macro functions and routines. Examples of closed code, or Inside-Macros-Only statements are %*Comment; %WHILE, %DO, %END, %GOTO, %IF-%THEN/%ELSE, and %LABEL: All of these statements are the same as SAS DATA step statements except that these statements program the Macro Processor. These statements allows for: 1) Conditional execution of Macro statements and the generation of SAS code 2) Executing code a given number of times 3) Branching within a Macro 4) Supplies values for Macro variables during Macro execution and 5) Creation of Macro variables and assigning values. Conditionally Generating SAS Code By using the %IF-%THEN-%ELSE macro statements, you can conditionally generate SAS code with a macro. Here is an example: %MACRO whatstep(info=,mydata=); %IF %UPCASE(&info)=PRINT %THEN %DO; PROC PRINT DATA=&mydata; RUN; %END; %ELSE %IF %UPCASE(&info)=REPORT %then %DO; OPTIONS NOdate NOnumber ps=18 ls=70 fmtsearch=(sasuser); PROC REPORT DATA=&mydata NOwd; COLUMN manager dept sales; WHERE sector='se'; FORMAT manager $mgrfmt. dept $deptfmt. sales dollar11.2; TITLE 'Sales for the Southeast Sector'; RUN; %END; %MEND whatstep; In this example, the macro whatstep assumes keyword parameters are set to default values. When you call a macro that needs keyword parameters, specify the parameter name followed by an equal sign and the value you want to assign the parameter. Here, the macro whatstep is called with INFO set to print and MYDATA set to grocery: %whatstep(info=print,mydata=grocery) Entering this macro call produces the following statements: PROC PRINT DATA=grocery NOobs; RUN; Because the macro processor is case sensitive, it's a good idea to use the %UPCASE function so that the program will evaluate your choice as PRINT even if you submit 'Print' or 'pRiNt'. Use of the %UPCASE macro function will make your macro more robust. MACRO %DO STATEMENTS A %DO statement or %DO loop can be invoked up the successful test from an %IF condition, such as to check for the presence of a given file in a specified drive and directory: %macro filechk; %IF %SYSFUNC(fileexist("&file"))=1 %THEN %DO; %PUT file exists; %END; %ELSE %PUT file does not exist; %mend; %LET file= C:\sas\Excel\test_99.xls; %filechk ; Macro %DO loops will run DATA and PROC steps multiple times. Although they look very much like DO loops in a DATA step, their purpose is different. For example, if you want to plot income against 15 variables defined as x1-x15, and compute the linear regression on y on xi, i=1,.., 15, you run both procedures 15 times with a %DO loop: * implement a macro to create 15 plots and univariate regressions; %LET nvar=15; DATA abc; INFILE 'c:\data\abc.dat' dlm=',' dsd; INPUT y x1-x&nvar ; RUN; /* Define the macro */ %MACRO regr; %DO i=1 %to &nvar; * j, the index number is now a LOCAL macro variable; PROC PLOT DATA=abc; PLOT y*x&i='+'; RUN; PROC REG DATA=abc; MODEL y=x&i; RUN; %END; %MEND regr; %regr RUN; To conditionally produce SAS code, you can append several files (dset1, dset2, ..., dset&mnindex) together ; %MACRO app_em(mnindex=); DATA all; SET %DO i=1 %to &mnindex; mydat&i %END; RUN; %MEND app_em; %app_em(mnindex=5) Or you could call a macro to write the file names: %MACRO set_dat(start=,end=); %DO i = &start %to &end; mydat&i /* no semicolon appears on this line */ %END; %MEND set_dat; DATA all; SET %set_dat(start=1,end=5); RUN; PROC PRINT DATA=all; run; A looping macro can be a shortcut to compute new variables that are the product of all possible pairs of k variables: < need to revise > %MACRO interact(var1=i, var2=v, j=1, k=5); %DO i = &j %to %EVAL(&k-1); &var1.&i=&var2.1 * &var2.%eval(&i+1); %END; %MEND; f. Functions Macro functions process one or more Macro expressions, called arguments, produce a new character string, the result or returned value. They can be either inside or outside a Macro. There are three categories: Character(%_______), numerical evaluation (%EVAL and %SYSEVAL), and quoting functions(%QUOTE). Macro character functions either change or provide information about the character string that is their argument. Most macro character functions have names that correspond to DATA step character functions, and are similar in the way each works, except that macro functions executes while SAS is constructing a DATA or PROC step. The DATA step function executes when the DATA STEP executes, and is treated as constant text by the macro porocessor, and unlike DATA step functions, Macro character functions may be paired with a "Q" for returning quoted results. The evaluation function is %EVAL. Because the macro processor is a character (string) handling facility, "numbers" in Macro expressions are treated as character strings. The %EVAL function expects the contents of a macro variable to be an integer in expressions and calculations are performed using integer arithmetic. The %EVAL function also evaluates logical expressions such as &vara=&varb. The quoting functions in the Macro language perform the activity equivalent to enclosing a portion of a SAS statement in single or double quotes. That the Macro Facility treats the expression with the function as a unit and not perform any evaluations on the expression. Quoting functions are used to cause the Macro Processor to treat special characters as text. Quoting functions are necessary because the Macro processor treats single quote (') and double quotes (") as text. %EVAL and %SYSEVAL: Evaluate Arithmetic Expressions The macro facility is primarily a character data handling facility. However, the macro processor can evaluate operands that represent numeric values. When the macro processor evaluates an expression that contains an arithmetic operator and operands that represent numbers, it temporarily converts the operands to numeric values and performs the integer arithmetic operation. The result of the evaluation is text. By default, arithmetic evaluation in most macro statements and functions is performed with integer arithmetic. The exception is the %SYSEVALF function. (See Evaluating Floating Point Operands below.) The following macro statements illustrate integer arithmetic evaluation: %LET a=%EVAL(1+2); %PUT The value of a is &a; %LET b=%EVAL(10*3); %PUT The value of b is &b; %LET c=%EVAL(4/2); %PUT The value of c is &c; %LET i=%EVAL(4/3); %PUT The value of i is &i; These statements write the following lines to the log file: The value of a is 3 The value of b is 30 The value of c is 2 The value of i is 1 Everything appears as you would expect until the result of the last statement is printed. The result is not the 1.33333333 you expect. If you divide integers that compute a result with a non-zero decimal, the %EVAL function discards the fractional part. When you get non integer strings, remember that the %EVAL function will not output the fractional portion; it performs only integer arithmetic. Also, note that when the macro processor evaluates an integer arithmetic expression that contains a character operand, it will generate an error. Only operands that contain characters representing integers or hexadecimal values are converted to numeric values. For example, the following statement shows an incorrect usage: %LET d=%EVAL(10.0+20.0); /* INCORRECT */ Since the %EVAL function supports only integer arithmetic, decimals are treated as strings, and therefore, the macro processor will not convert a value containing a 'period' into a number. The operands are evaluated as character operands. This statement produces the following error message: ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 10.0+20.0 How to Evaluate Floating Point Operands with a Macro Variable The %SYSEVALF function handles floating point comparisons and calculations. It evaluates arithmetic expressions with operands that contain real numbers. For example, the following expressions in the %SYSEVALF function are evaluated as you would expect with floating point arithmetic: %LET a=%SYSEVALF(10.0*3.0); %LET b=%SYSEVALF(10.5+20.8); %LET c=%SYSEVALF(4/3); %PUT 10.0*3.0 = &a; %PUT 10.5+20.8 = &b; %PUT 4/3 = &c; The three %PUT statements display the following lines in the log file: 10.0*3.0 = 30 10.5+20.8 = 31.3 5/3 = 1.33333333 When the %SYSEVALF function evaluates arithmetic expressions, it temporarily converts the operands that represent numbers into floating point values. The result of the evaluation can represent a floating point value, but as with integer arithmetic expressions, the result is always text. The %SYSEVALF function provides conversion various type specifications including INTEGER, CEIL, and FLOOR. For example, these %PUT statements %LET a=2.5; %PUT %SYSEVALF(&a,integer); %PUT %SYSEVALF(&a,ceil); %PUT %SYSEVALF(&a,floor); These statements return 2, 3, and 2, respectively. These conversion types tailor the value returned by %SYSEVALF so that it can be used in other macro expressions that require integer or Boolean values. CAUTION: Specify a conversion type for the %SYSEVALF function. If you use the %SYSEVALF function in macro expressions or assign its results to macro variables that are used in other macro expressions, then errors or unexpected results may occur if the %SYSEVALF function returns missing or floating point values. To prevent errors, specify a conversion type that returns a value compatible with other macro expressions. See "%SYSEVALF" in Chapter 13, "Macro Language Dictionary" for more information on using conversion types. Other Functions On a UNIX system the command pwd prints the working directory. Within a program you can insert the %SYSGET function to determine the current directory: %LET prog = %SYSGET(PWD); %PUT &prog; /home3/robinh/sas Note that PWD needs to be capitalized within the SAS function, even though the UNIX command itself must be entered in lower case (pwd). SYMGET In the DATA step, SYMGET returns a character value that is the maximum length of a DATA step character variable. A returned value that is longer is truncated. * example; %LET var=wfE; DATA _null_; hand=0; IF (UPCASE(SYMGET('var')) EQ 'WFE') then hand=1; CALL SYMPUT ("hnd",hand); RUN; %put &hnd. ; in the log file a 1 is printed Print a Data Set if it Exists Use a macro language function, %sysfunc(), to call the SAS language function, exist(), as follows: %macro tst; %if %SYSFUNC(fileexist(dat.xyz)) %then %do; PROC PRINT DATA =dat.xyz; title "data set name is xyz"; run; %end; %mend tst; %tst; G. AutoCall Facility The macro facility AUTOCALL feature allows you to store the source statements for macros in a file, associate the file with a SAS job or session, and call or include the macros as needed. The macro definition does not have to be part of the current program. By specifying the MAUTOSOURCE system options and associating the file reference (DD) SASAUTOS with a library of Marcos, the AUTOCALL facility will automatically define and execute a Macro when it is called into a SAS job. This facility is especially useful for defining your own Macro functions, which you can store in an AUTOCALL library. SAS provides some special macros in the SAS AUTOCALL library supplies with Base SAS. H. System Options In production and tested code, macro statements do not usually need to appear in the log file when the program is run. Not reading the macro statements can be a problem when complex code is involved and the macro is not working properly. Error codes for macros lie between 1000 and 4000 and indicate the problem occurred in the macro facility. System options such as MPRINT, MLOGIC, SYMBOLGEN, and MACROGEN are available and can be used either separately or in combination. The options display information on the SAS log giving detail about the compilation or execution of a macro. The type of messages displayed in the log depends on the option chosen. Issue the following statement as a rule, when testing code with macros: OPTIONS Mprint; The SAS macro processor will then write to your log file any statements (with parameters inserted and macro expressions resolved) that macros in your SAS program generate. You will observe the literal statements that the SAS macro processor has generated for the SAS interpreter to "see" and execute. If you have a macro that iterates many times then the log file can get rather large and you may even run into disk space and/or processing time trouble. Once you're done debugging your macros and they work fine then issue the statement: OPTIONS NOMprint; Two other useful SAS global options for macro debugging or program auditing are * SYMBOLGEN (or NOSYMBOLGEN) * MLOGIC (or (NO)MLOGIC) I. Quick Rules There are several general rules of using macros which will greatly assist you in using them effectively. In the batch environment, new macro writers should follow: 1. Define all macros before use, preferably at the beginning of the SAS program or AUTOCALLed. 2. Know the referencing environment, global, local, and current 3. Use systems options in debugging macros 4. Use keyword parameters with macro variable defaults 5. Document macros with %* ; as single line comments;