3. proc sort data=perm.all out=current; where put(begin_date,monyy5.)= "%substr(&sysdate,3,5)" and begin_date ge "&sysdate"d; by begin_date location course_title; run; proc print data=current noobs n; by begin_date location course_title; var student_name student_company paid; title "Course Registration as of &sysdate"; run; Suppose you submit this program every day to create registration listings for courses to be held later in the current month. Conditional Processing
4. Every Friday you also submit this program to create a summary of revenue generated so far in the current month: proc sort data=perm.all out=current; where put(begin_date,monyy5.)= "%substr(&sysdate,3,5)" and begin_date le "&sysdate"d; by begin_date location course_title; run; proc means data=current maxdec=0 sum; by begin_date location course_title; var fee; class paid; title "Revenue for Courses as of &sysdate"; run; The Need for Macro-Level Programming Conditional Processing
5. You want to automate the process so only one program is required. This program should always submit the daily report and conditionally submit the weekly report. The Need for Macro-Level Programming Conditional Processing
6. Is it Friday? Yes Always Print the Daily Report The Need for Macro-Level Programming Conditional Processing
7. Conditional Execution You can perform conditional execution at the macro level with %IF-%THEN and %ELSE statements. General form of %IF-%THEN and %ELSE statements: %IF expression %THEN text ; %ELSE text ; expression can be any valid macro expression. The %ELSE statement is optional . Conditional Processing
8.
9. Use %DO and %END statements following %THEN or %ELSE to submit text that contains semicolons. General form of %DO-%END with %IF-%THEN and %ELSE statements: %IF expression %THEN %DO ; statemen t; statemen t;... %END ; %ELSE %DO ; statemen t; statemen t;... %END ; Conditional Execution Conditional Processing
10. %IF expression %THEN %DO ; statemen t; statemen t;... %END ; %ELSE %DO ; statemen t; statemen t;... %END ; The statements %IF-%THEN, %ELSE, %DO, and %END can only be used inside a macro definition. Conditional Execution Conditional Processing
11. During macro compilation, macro statements are checked for syntax errors. If a macro definition contains macro statement syntax errors, error messages are written to the SAS log. Syntax errors create a nonexecutable (dumm y) macro. Conditional Processing
12. Introduce a syntax error and show resulting compilation messages. %macro printit; %if &syslast ne _NULL_ then %do; proc print data=_last_(obs=5); title "Last Created Data Set Is &syslast"; run; %end; %mend; Compilation of Macro Programming Statements Conditional Processing
14. When the macro processor receives %macro-nam e, it executes compiled macro language statements such as %IF-%THEN. The values of macro variables used within the %IF logical expression are resolved during macro execution . The %IF logical expression is automatically evaluated. The %EVAL function is not necessary. Conditional Processing
15. Example: Compile the PRINTIT macro shown below. Show processing resulting from a call to it. %macro printit; %if &syslast ne _NULL_ %then %do; proc print data=_last_(obs=5); title "Last Created Data Set Is &syslast"; run; %end; %mend; %printit Macro Execution with Conditional Processing Conditional Processing
16. When %printit is submitted, the macro processor locates WORK.SASMACR.PRINTIT.MACRO. SAS Compiler Global Table SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor %printit Input Stack WORK.SASMACR.PRINTIT.MACRO %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
17. Because the %IF expression is true, the %THEN %DO block is processed . SAS Compiler Global Table SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor %if &syslast ne _NULL_ %then ... Input Stack WORK.SASMACR.PRINTIT.MACRO %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
18. The macro processor places the text after the %DO on the input stack. SAS Compiler Global Table SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor Input Stack WORK.SASMACR.PRINTIT.MACRO proc print...; title " ... "; run; %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
19. Word scanning proceeds as usual. SAS Compiler Global Table proc print ...; title "... SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor &SYSLAST Input Stack WORK.SASMACR.PRINTIT.MACRO ... "; run; %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
20. If a macro trigger is encountered, the macro reference is passed to the macro processor for resolution. SAS Compiler Global Table proc print ...; title “... SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor &SYSLAST Input Stack WORK.SASMACR.PRINTIT.MACRO ... "; run; %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
21. The macro processor returns resolved values to the input stack. SAS Compiler Global Table proc print ...; title "... SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor Input Stack WORK.SASMACR.PRINTIT.MACRO WORK.X "; run; %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
22. Macro execution pauses while the PROC PRINT step executes. SAS Compiler Global Table proc print ...; title "...work.x"; SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor run; Input Stack WORK.SASMACR.PRINTIT.MACRO %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
23. Macro execution stops when the %MEND statement is encountered. SAS Compiler Global Table SYSLAST WORK.X SYSDAY Tuesday Word Scanner Macro Processor Input Stack WORK.SASMACR.PRINTIT.MACRO %macro printit; %if &syslast ne _NULL_ %then do; proc print data=_last_(obs=5); title "Last ... Is &syslast"; run; %end; %mend printit; Macro Execution with Conditional Processing Conditional Processing
24. For debugging or confirmation, you may want information on an executing macro. You can use the MPRINT, SYMBOLGEN, and MLOGIC system options that instruct the macro processor to display execution information in the SAS log. Conditional Processing
25. %macro printit; %if &syslast ne _NULL_ %then %do; proc print data=_last_(obs=5); title "Last Created Data Set Is &syslast"; run; %end; %mend; options mprint mlogic symbolgen; %printit data x; y=1; run; %printit Monitoring Execution Conditional Processing
27. SAS Log (continued) Monitoring Execution Conditional Processing
28. Recall the daily and weekly reports described at the start of this section. The program shown on the next slide defines and executes a macro that unconditionally submits the daily report and submits the weekly report only if the current day is Friday. Conditional Processing
29. %macro reports; proc sort data=perm.all out=current; where put(begin_date,monyy7.)= "%substr(&sysdate9,3,7)" and begin_date ge "&sysdate9"d; by begin_date location course_title; run; proc print data=current noobs n; by begin_date location course_title; var name company paid; title "Course Registration as of &sysdate"; run; continued... Conditional Processing of Steps Conditional Processing
30. %if &sysday=Friday %then %do; proc sort data=perm.all out=current; where put(begin_date,monyy7.)= "%substr(&sysdate9,3,7)" and begin_date le "&sysdate9"d; by begin_date location course_title; run; proc means data=current maxdec=0 sum; by begin_date location course_title; var fee; class paid; title "Revenue for Courses as of &sysdate9"; run; %end; %mend reports; Conditional Processing of Steps Conditional Processing
31. %macro reports; %include 'file-containing-daily-report-code'; %if &sysday=Friday %then %do; %include 'file-containing-weekly-report-code'; %end; %mend reports; options mprint; %reports Blocks of SAS statements can be stored in external files and inserted into the input stack using the %INCLUDE statement . Conditional Processing of Steps Conditional Processing
32. %macro daily; proc sort data=perm.all out=current; where put(begin_date,monyy7.)= "%substr(&sysdate9,3,7)" and begin_date ge "&sysdate9"d; by begin_date location course_title; run; proc print data=current noobs n; by begin_date location course_title; var name company paid; title "Course Registration as of &sysdate9"; run; %mend daily ; Blocks of SAS statements can be stored as macro programs and inserted into the input stack using macro calls. Conditional Processing of Steps Conditional Processing
33. %macro weekly; proc sort data=perm.all out=current; where put(begin_date,monyy7.)= "%substr(&sysdate9,3,7)" and begin_date le "&sysdate9"d; by begin_date location course_title; run; proc means data=current maxdec=0 sum; by begin_date location course_title; var fee; class paid; title "Revenue for Courses as of &sysdate9"; run; %mend weekly; Conditional Processing of Steps Conditional Processing
34. %macro reports; %daily %if &sysday=Friday %then %do; %weekly %end; %mend reports; %reports Create a macro called REPORTS that will always call the DAILY macro and conditionally call the WEEKLY macro. Conditional Processing of Steps Conditional Processing
35. It is possible to conditionally insert individual statements into the input stack, even in the middle of a step . Conditional Processing of Statements Conditional Processing
36.
37. The text processed as the result of conditional logic can be a small part of a SAS statement. This makes it possible to conditionally insert text into the middle of a statement. Conditional Processing of Parts of Statements(Self Study) Conditional Processing
38. Print a table of frequency counts from a SAS data set. Generate either a one-way table or a two-way table, based on the value of a macro parameter. Conditional Processing of Parts of Statements(Self Study) Conditional Processing
39. %macro counts (cols=_all_,rows=,dsn=&syslast); title "Frequency Counts for %upcase(&dsn) data set"; proc freq data=&dsn; tables %if &rows ne %then &rows *; &cols; run; %mend counts; options mprint mlogic; %counts(dsn=perm.all, cols=paid, rows=course_number) %counts(dsn=perm.all, cols=paid) Conditional Processing of Parts of Statements(Self Study) Conditional Processing
40. Partial SAS Log Conditional Processing of Parts of Statements(Self Study) Conditional Processing
41. Partial SAS Log Conditional Processing of Parts of Statements(Self Study) Conditional Processing
42. %IF-%THEN Compared to IF-THEN There are several important differences between the macro %IF-%THEN statement and the DATA step IF-THEN statement. Conditional Processing
45. Comparisons made in %IF expressions are case sensitive. Example: Create an unsuccessful comparison due to improper case of program text. Conditional Processing
46. %macro prtlast; %if &syslast=_null_ %then %do; %put No data sets created yet.; %end; %else %do; proc print; title "Last Created Data Set is &syslast"; run; %end; %mend; options mprint mlogic symbolgen; %prtlast Conditional Processing
48. A good technique when writing macros is to validate a macro variable’s value before generating any SAS code based on this value . Example: Create a report only if the value specified for the SITE parameter is DALLAS , SEATTLE , or BOSTON . Conditional Processing
49. %macro courses(site); %let site=%upcase(&site); %if &site=DALLAS or &site=SEATTLE or &site=BOSTON %then %do; proc print data=perm.schedule; where upcase(location)="&site"; title "COURSES OFFERED AT &site TRAINING CENTER"; run; %end; %else %do; %put Sorry, no courses taught at &site..; %end; %mend courses; Pattern Matching in Macro Comparisons Conditional Processing
50. The macro call %courses(Dallas) created the report shown below. Pattern Matching in Macro Comparisons Conditional Processing
51. The macro call %courses(LA) created the report shown below. Pattern Matching in Macro Comparisons Conditional Processing
52. You can use the %INDEX function to simplify checking the value of a macro variable against a known list of values. General form of the %INDEX function: %INDEX ( argument 1, argument 2) Pattern Matching in Macro Comparisons Conditional Processing
53.
54.
55.
56. 1. If a macro-based program is used to generate SAS code, write and debug the desired SAS program without any macro coding. Make sure the SAS program runs with hard-coded programming constants on a fixed set of data. Many SAS programmers develop macro-based programs as follows: Conditional Processing
57. 2. Generalize the program by removing hard-coded programming constants and substituting macro variable references. Initialize the macro variables with %LET statements and try different values for the macro variables. Use the SYMBOLGEN system option to assist in debugging or confirmation. You may need to adjust the basic program to make it more generalized. Tips on Writing Macro Programs Conditional Processing
58. 3. Create a macro definition by inserting %MACRO and %MEND statements around your program. Convert %LET statements to macro parameters, if desired. Call the macro using different parameter values. Use the MPRINT and SYMBOLGEN system options for debugging. Tips on Writing Macro Programs Conditional Processing
59. 4. Add macro-level programming statements such as %IF-%THEN after the macro executes successfully. Thoroughly test any macro-level programming logic. Use the MLOGIC, MPRINT, and SYMBOLGEN system options for debugging. Tips on Writing Macro Programs Conditional Processing
60. This process enables more rapid development and debugging because you are isolating syntax and logic at the SAS code level from the syntax and logic at the macro level . Tips on Writing Macro Programs Conditional Processing
65. Global Symbol Table The Global Symbol Table Global and Local Symbol Table SYSDATE 19JUN00 SYSDAY Monday SYSVER 8.00 . . . . . . uservar1 value1 uservar2 value2 Variable Value
66.
67.
68.
69.
70. Local Symbol Table The memory used by a local table can be reused when the table is deleted after macro execution. Therefore, use local variables instead of global variables whenever possible. The Local Symbol Table Global and Local Symbol Table parameter1 value1 parameter2 value2 . . . . . . uservar1 value1 uservar2 value2 Variable Value
71.
72. General form of the %LOCAL statement: %LOCAL macrovar1 macrovar2 . . . ; The Local Symbol Table Global and Local Symbol Table
73.
74. A local table is not created until a request is made to create a local variable. Macros that do not create local variables do not have a local table. The SYMPUT routine and older versions of PROC SQL can create local variables only if the local table already exists. The Local Symbol Table Global and Local Symbol Table
75. When the macro processor receives a request to create or update a macro variable during macro execution , the macro processor follows these rules: Request during macro call: %LET MACVAR=VALUE ; Does MACVAR already exist in the local table? Yes Update MACVAR with VALUE in the local table. Does MACVAR already exist in the global table? Update MACVAR with VALUE in the global table. Create MACVAR and assign it VALUE in the local table. No No Yes Macro Processor Global and Local Symbol Table
76. Rules for Resolving Variables To resolve a macro variable reference during macro execution , the macro processor follows these rules: Request during macro call: &MACVAR Yes Retrieve its value from the local table. Retrieve its value from the global table. Give the tokens back to the wordscanner. Issue warning message in SAS log: Apparent symbolic reference MACVAR not resolved. No No Yes Macro Processor Does MACVAR exist in the global table? Does MACVAR exist in the local table? Global and Local Symbol Table
77. Multiple local tables can exist concurrently during macro execution. Example: Define two macros. Call one within the other. %macro outer; %local x; %let x=1; %inner %mend outer; %macro inner; %local y; %let y=&x; %mend inner; Create the global macro variable X with a value of 0. %let x=0; Global Table X 0 Global and Local Symbol Table
78. When the OUTER macro is called, a local table is created when the %LOCAL statement executes. State of the symbol tables before the INNER macro is called. %macro outer; %local x; %let x=1; %inner %mend outer; %macro inner; %local y; %let y=&x; %mend inner; %outer Global Table X 0 OUTER Local Table X 1 What happens if the %LOCAL statement in the OUTER macro is omitted? Global and Local Symbol Table
79. Rule: A nested macro call can create its own local symbol table. This table is in addition to any other tables that may currently exist. State of symbol tables after %LOCAL executes in the INNER macro. %macro outer; %local x; %let x=1; %inner %mend outer; %macro inner; %local y; %let y=&x; %mend inner; %outer Global Table X 0 OUTER Local Table X 1 INNER Local Table Y Global and Local Symbol Table
80. Rule: The macro processor resolves a macro variable reference by searching symbol tables in the reverse order in which they were created: 1. current local table 2. previously created local tables 3. global table. State of symbol tables after %LET executes in INNER macro. %outer Global Table X 0 OUTER Local Table X 1 INNER Local Table Y 1 %macro outer; %local x; %let x=1; %inner %mend outer; %macro inner; %local y; %let y=&x; %mend inner; Global and Local Symbol Table
81. Multiple Local Tables Once the INNER macro finishes execution, its local table is removed. Control passes back to the OUTER macro. State of the symbol tables after the INNER macro executes. %macro outer; %local x; %let x=1; %inner %mend outer; %macro inner; %local y; %let y=&x; %mend inner; %outer Global Table X 0 OUTER Local Table X 1 State of symbol tables after the OUTER macro executes. Global Table X 0 Global and Local Symbol Table
89. Declare the index variable of a macro loop as a local variable to prevent accidental contamination of macro variables of the same name in other symbol tables. Caution No code is sent to the compiler. The %PUT statements are executed by the macro processor. Iterative Processing
90. Statements generated by a macro loop can be placed inside a step. Generating Complete Statements Iterative Processing
91. Example: Generate repetitive pairs of statements within a DATA step program. %macro roman(start=1,stop=10,incr=1); %local i; data _null_; %do i=&start %to &stop %by &incr; value=&i; put "Roman form of &i is ” value roman12.; %end; run; %mend roman; options mprint; %roman(start=2000,stop=2006,incr=2) Generating Complete Statements Iterative Processing
92. Partial SAS Log Generating Complete Statements Iterative Processing
93.
94.
95. Generating Data-Dependent SAS Code Example: The PERM.SCHEDULE data set contains schedule information for all training locations. Create a separate data set for the schedule of each individual location without knowing the number of locations. Iterative Processing
96. Partial SAS log showing resulting data sets for each location: Generating Data-Dependent SAS Code Iterative Processing
97. %macro sites; %local i; proc sort data=perm.schedule(keep=location) out=values nodupkey; by location; run; data _null_; set values end=last; call symput('site'||left(_n_),trim(location)); if last then call symput('count',_n_); run; %do i=1 %to &count; %put SITE&i is &&site&i; %end; %mend sites; %sites Generating Data-Dependent SAS Code Iterative Processing
98. The SITE variables are created in the local symbol table that was initialized by the %local i; statement at the beginning of macro execution. The macro language does not support variable lists or array structures. However, you can use iterative macro loops to create or process a series of related macro variables. Generating Data-Dependent SAS Code Iterative Processing
99. Text written to the SAS Log Generating Data-Dependent SAS Code Iterative Processing
105. Operator Mnemonic Meaning Precedence ** exponentiation 1 ^ NOT logical not 1 * multiplication 2 / division 2 + addition 3 - subtraction 3 < LT less than 4 <= LE less than or equal 4 = EQ equal 4 ^= NE not equal 4 > GT greater than 4 >= GE greater than or equal 4 & AND logical and 5 | OR logical or 6 The tokens shown in the two leftmost columns have arithmetic or logical meaning to the %EVAL function. Arithmetic and Logical Operation
106. Example: Use the %EVAL function to evaluate various expressions. These statements Generate these results %put value=%eval(10 lt 2); value=0 %put value=10+2; value=10+2 %put value=%eval(10+2); value=12 %let counter=2; %let counter=%eval(&counter+1); %put counter=&counter; counter=3 %let numer=2; %let denom=8; %put value=%eval(&numer/&denom); value=0 Arithmetic and Logical Operation
107. These statements Generate these results %let numer=2; %let denom=8; %put value=%eval(&numer/&denom*&denom); value=2 %put value=%eval(&denom*&numer/&denom); value=0 %let real=2.4; %let int=8; %put value=%eval(&real+&int); value= In the last example, the %EVAL function creates an error condition and returns a null value. ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required.The condition was:2.4+8 Arithmetic and Logical Operation
108. Example: Use the %EVAL function to compute the final year of a range. %let firstyr=2000; %let numyears=2; %let finalyr= %eval(&firstyr+&numyears-1); proc print data=perm.schedule; where year(begin_date) between &firstyr and &finalyr; title “All Courses Scheduled”; title2 “&firstyr through &finalyr”; run; Arithmetic and Logical Operation
109. Example: Use the %EVAL function to compute the final year of a range. Arithmetic and Logical Operation
110. Example: Use the %EVAL function to compute the first year of a range based on the SYSDATE macro variable. %let thisyr=%sysfunc(today(),year4.); %let lastyr=%eval(&thisyr-1); proc print data=perm.schedule; where year(begin_date) between &lastyr and &thisyr; title "All Courses Scheduled during&lastyr and" " &thisyr"; title2 "(as of &sysdate9.)"; run; Arithmetic and Logical Operations Arithmetic and Logical Operation
111. Example: Use the %EVAL function to compute the first year of a range based on the SYSDATE macro variable. Arithmetic and Logical Operations Arithmetic and Logical Operation
112. %SCAN( tex t, expression , delimiter s) %SUBSTR( tex t, expression , expression ) %IF expression %THEN tex t; %DO inde x= expression %TO expression %BY expression ; %DO %UNTIL (expression) ; %DO %WHILE (expression) ; Any macro language function or statement that requires a numeric or logical expression automatically invokes the %EVAL function: Arithmetic and Logical Operation
113. %substr(&var,%length(&var)-1) %substr(&var,%eval(%length(&var)-1)) The following %SUBSTR functions generate the same result: The second example is less efficient because the %EVAL function is invoked twice: 1. explicitly by the %EVAL function 2. implicitly by the %SUBSTR function. Arithmetic and Logical Operation
114. General form of the %DO %WHILE statement: You can perform conditional iteration in macros with %DO %WHILE and %DO %UNTIL statements. %DO %WHILE ( expression ); text %END ; General form of the %DO %UNTIL statement: %DO %UNTIL ( expression ); text %END ; expression can be any valid macro expression. Arithmetic and Logical Operation
115.
116. Conditional Iteration Example: Identify words in a list supplied as a macro parameter. Start with the first word and continue as long as more words are found. If no first word is found, display a message. %macro words(text,delim=%str( )); %local i word; %let i=1; %let word=%scan(&text,&i,&delim); %do %while (&word ne ); %put Word number &i is: &word; %let i=%eval(&i+1); %let word=%scan(&text,&i,&delim); %end; %if &i=1 %then %put Text is blank.; %mend words; %words(This is a test) Arithmetic and Logical Operation
117. Conditional Iteration Example: Identify words in a list supplied as a macro parameter. Start with the first word and continue as long as more words are found. If no first word is found, display a message. Partial SAS Log Arithmetic and Logical Operation
118. Conditional Iteration Example: Identify words in a list supplied as a macro parameter. Stop when no more words can be found. Assume that there is always at least one word . %macro words(text,delim=%str( )); %local i word; %let i=1; %let word=%scan(&text,&i,&delim); %do %until (&word = ); %put Word number &i is: &word; %let i=%eval(&i+1); %let word=%scan(&text,&i,&delim); %end; %if &i=1 %then %put Text is blank.; %mend words; %words(This is a test) Arithmetic and Logical Operation
119. Conditional Iteration Example: Identify words in a list supplied as a macro parameter. Stop when no more words can be found. Assume that there is always at least one word . Partial SAS Log Arithmetic and Logical Operation