html5-img
1 / 33

Paul Sherman

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

ryann
Télécharger la présentation

Paul Sherman

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 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

  2. 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

  3. 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

  4. 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

  5. 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

  6. 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

  7. 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

  8. Comments About Comments • Depends on when text is removed, • And what text is protected Block /* */ before Macro %* ; during Statement * ; after

  9. 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

  10. What is a Macro Block Boundary? The place where macro processor switches between resolution and execution modes

  11. 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

  12. 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;

  13. 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;

  14. Open Code • Easy to read X-Y fashion • LINE numbers persistent to SAS session

  15. 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.

  16. 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

  17. 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)

  18. 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.

  19. 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

  20. 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.

  21. 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)

  22. 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

  23. Call Execute Code Data step phase (Block):(Char) Call Execute phase “lean” macro (Loop):(Char) “lean” macro

  24. A Better Way • Turn off everything possible • Explicity control the Log as you want options nosource nonotes nomprint nomlogic nosymbolgen ;

  25. Example Transpose & Print a dataset Data to; set from; Proc SORT; Proc TRANSPOSE; Proc PRINT; Proc DATASETS; run; quit; everywhere open code

  26. Best Practice • Macros are verbs • Datasets are nouns MAIN COPYDAT Separate XPOSE SORT TRANSPOSE SHOWDAT Encapsulate REMOVE %main; Open code: program entry point

  27. 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”

  28. Using the Log Manager • Notify the Log %putlog(“I was here”); • Throw an Exception %throw(arg &arg. not allowed);

  29. main() { init() { } dothis() { } dothat() { } make(foo) { creating... a=. _ERROR_=1 _N_=1 remove(foo) { } } finalize() { } } Example MAIN INIT DoThis DoThat MAKE FINALIZE

  30. 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;

  31. 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

  32. 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

  33. 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

More Related