330 likes | 447 Views
Tips for Debugging SAS Macros. Article & Slides: www.idiom.com / ~sherman / paul / pubs / macnotes. SAS/MACRO NOTES: Lines and Columns in the Log. Paul Sherman. Topics to be Covered. What’s wrong with Macros How SAS reports Lines & Columns Comments about comments
E N D
Tips for Debugging SAS Macros Article & Slides: www.idiom.com / ~sherman / paul / pubs / macnotes SAS/MACRO NOTES: Lines and Columns in the Log Paul Sherman
Topics to be Covered • What’s wrong with Macros • How SAS reports Lines & Columns • Comments about comments • Open Code and Macro Code • Quirks of Call Execute • Best Practices • Using the Log Manager
Why Important for DP & BI? • You have a generic macro • Invoked many times per summary data • Only some invokes give “funny” results • Missing graph lines • Overprinted labels • Incorrect basis
What’s Wrong With Macros • They're programs that write programs • (Line):(Column) doesn't make sense • LINE# changes with each submit • LINE# is almost always 1 • They give me a headache
What We See NOTE: Character values have been converted to numeric values at the places given by: (Line:Column). 1:27 NOTE: Missing values were generated as a result of performing an operation on missing values. Each place is given by: (Number of times) at (Line):(Column). 143 at 1:54 2557 at 1:112
When We See These Errors • Building annotate data sets • Data cleaning • Creating numeric from macro variables • Merging sets with non-identical variables • Putting code inside a macro
How SAS Reports Line & Column Open Code Macro Code NOTE: reports (Block):(Character) (Line):(Column) (Loop):(Character) LINE represents Submitted SAS line Statement "block" Relative to each submit Persistent as of start of session LINE is Relative to left margin COLUMN is From end of last statement block
Comments About Comments • Depends on when text is removed, • And what text is protected Block /* */ before Macro %* ; during Statement * ; after
Turning Off Code Open Code *%dont_run_me_now; Macro Code %macro xx; *%put; data x; put x; %mend; %macro xx; * data x; put x; %mend; %macro xx; put x; %mend; Out-of-place DATA step statement
What is a Macro Block Boundary? The place where macro processor switches between resolution and execution modes
What is a Macro Block Boundary? %macro foo; %mend; %put; %put; data _null_; do i=1 to 10; end; run; Block #1 %put; %if x eq y %then %do; %put x; %end; Block #2
Macro Comments %macro mymac; %mend; Block Comment /* */ Immediately removed Macro Comment %* ; Char #2 Bad DATA step Block #1 X (Line):(Column) 1:57 Char #1 %mymac;
Statement Comments %macro mymac; %mend; Statement Comment * ; Block #1 %put ...; Block #2 Char #1 . Bad DATA step . . Block #3 X Char #2 (Line):(Column) 3:63 %mymac;
Open Code • Easy to read X-Y fashion • LINE numbers persistent to SAS session
1 2 3 4 5 6 7 Column Line #1 Line #4 Line Open Code options nosource; data _null_; ..format a 4.2; ..a='junk'; ..run; Column #5 NOTE: Invalid numeric data, 'junk', at line 4 column 5.
Line Number Persistence • Each time you submit, you get a new # • Must ENDSAS; to reset line count options nosource; data _null_; format a 4.2; a='junk'; run; NOTE: Invalid numeric data, 'junk', at line 4 column 4. 9 14
Macro Code • All code is a single line • LINE number is # "blocks" to bad code • COLUMN is position within bad block (Line):(Column) means (Block):(Char)
14 10 2 5 32 39 Character Block Macro Code %macro foo; %mend; ..%put; ..data _null_; ....format a 4.2; ....a='junk'; Block #1 Char #41 1 NOTE: Invalid numeric data, 'junk', at line 1 column 39.
A Few Simple Rules • Block numbers start with non-macro code and increment at macro code boundaries • Character position #1 of Block #1 starts immediately after %mend statement • Statement comments are non-macro blocks and do not remove macro code
Example 4 %macro good; data _null_; format a 4.2; a=1.7; %mend; %macro bad; data _null_; format a 4.2; a='junk'; %mend; %macro all; * statement comment ; ..%bad; %good; ..%bad; %mend; %all; Char #1 NOTE: Invalid numeric data, 'junk', at line 1 column 33. NOTE: Invalid numeric data, 'junk', at line 1 column 33.
Call Execute Code • All Data step statements executed first • Macro invoked after Data step • LINE number is Data step loop count • # loops is _n_ (Line):(Column) means (Loop):(Char)
Call Execute Code %macro mymac; data _null_; run; %put; data _null_; run; %mend; %macro iter; data _null_; set iterator; call execute(‘%mymac’); run; %mend; “lean” macro always one block
Call Execute Code Data step phase (Block):(Char) Call Execute phase “lean” macro (Loop):(Char) “lean” macro
A Better Way • Turn off everything possible • Explicity control the Log as you want options nosource nonotes nomprint nomlogic nosymbolgen ;
Example Transpose & Print a dataset Data to; set from; Proc SORT; Proc TRANSPOSE; Proc PRINT; Proc DATASETS; run; quit; everywhere open code
Best Practice • Macros are verbs • Datasets are nouns MAIN COPYDAT Separate XPOSE SORT TRANSPOSE SHOWDAT Encapsulate REMOVE %main; Open code: program entry point
Using the Log Manager • %include \\...\...\bloknote.sas; • Program starting point %bloknote(START, mainmac()); … %bloknote(END); • Every sub-macro %bloknote(OPEN, mymac(&arg.)); … %bloknote(CLOSE); WUSS 2005, “Intelligent SAS Log Manager”
Using the Log Manager • Notify the Log %putlog(“I was here”); • Throw an Exception %throw(arg &arg. not allowed);
main() { init() { } dothis() { } dothat() { } make(foo) { creating... a=. _ERROR_=1 _N_=1 remove(foo) { } } finalize() { } } Example MAIN INIT DoThis DoThat MAKE FINALIZE
main() { init() { } dothis() { } dothat() { } make(foo) { creating... a=. _ERROR_=1 _N_=1 remove(foo) { } } finalize() { } } Example MAKE %macro make(dat); %bloknote(OPEN,); %putlog(creating); data _null_; format a 4.; a=today(); a='junk'; run; %remove(&dat.); %bloknote(CLOSE); %mend;
Conclusion • SAS reports Line:Column in 3 ways • Open code → (Line):(Column) • Macro code → (Block):(Char) • Call Execute → (Loop):(Char) • Statement comments act like statements • Follow O-O style of program development • Separate • Encapsulate • Explicitly notify status & exceptions
Acknowledgments • Rohit Dhanjal, Sunil Gupta, Mandyam Srirama Extremely useful discussions on debugging SAS Macros • Issam Elayle Testing examples on version 9.1 • Kirk, Patrick, Lauren Invitation to present in their section
Thanks! Paul D Sherman (408) 383 - 0471 sherman @ idiom.com • Try this at home • Test with PROC's not DATA steps • Call Execute calling macro which Call Executes another macro which has errors www.idiom.com / ~sherman / paul / pubs / macnotes Further Study