Transcript DPR-Sherman

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
NOTE:
reports
LINE
represents
Open Code
Macro Code
(Line):(Column)
(Block):(Character)
(Loop):(Character)
Submitted SAS line
Statement "block"
Relative to each
Persistent
as
of
start
LINE is
submit
of session
COLUMN is Relative to left margin From end of last
statement block
Comments About Comments
• Depends on when text is removed,
• And what text is protected
Block
Macro
Statement
/* */
%* ;
*
;
before
during
after
Turning Off Code
Open Code
*%dont_run_me_now;
Macro Code
%macro xx; *%put; data x; put x; %mend;
%macro xx; *
%macro xx;
data x; put x; %mend;
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;
%put; %put;
data _null_;
do i=1 to 10; end;
run;
Block #1
%put;
%if x eq y %then %do; %put x;
%end;
%mend;
Block #2
Macro Comments
%macro mymac;
/*
Block Comment
*/
%*
Macro Comment
;
Immediately
removed
Char #2
Bad DATA step
Block #1
X
%mend;
%mymac;
Char #1
(Line):(Column)
1:57
Statement Comments
%macro mymac;
* Statement Comment
;
Block #1
%put ...;
.
.
.
Block #2
Char #1
Bad DATA step
%mend;
%mymac;
Block #3
X
Char #2
(Line):(Column)
3:63
Open Code
• Easy to read X-Y fashion
• LINE numbers persistent to SAS session
Open Code
1234 5 67
options nosource;
data _null_;
..format a 4.2;
..a='junk';
..run;
Line #1
Line #4
Column
Column #5
Line
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)
Macro Code
%macro foo;
..%put;
2
10
5
14
..data _null_;
Block #1
32
....format a 4.2;
39
Block
....a='junk';
%mend;1
Character
Char #41
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;
Char #1
%mend;
NOTE: Invalid numeric data,
%all;
'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;
“lean” macro
%put;
always one block
data _null_; run;
%mend;
%macro iter;
data _null_;
set iterator;
call execute(‘%mymac’);
run;
%mend;
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
Proc
Proc
Proc
Proc
to; set from;
SORT;
TRANSPOSE;
PRINT;
DATASETS; run; quit;
everywhere open code
Best Practice
• Macros are verbs
• Datasets are nouns
MAIN
COPYDAT
Separate
XPOSE
SORT
TRANSPOSE
Encapsulate
SHOWDAT
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);
Example
MAIN
INIT
DoThis
DoThat
MAKE
FINALIZE
main() {
init() {
}
dothis() {
}
dothat() {
}
make(foo) {
creating...
a=. _ERROR_=1 _N_=1
remove(foo) {
}
}
finalize() {
}
}
main() {
Example
init() {
}
MAKE
dothis() {
%macro make(dat);
}
%bloknote(OPEN,);
dothat() {
%putlog(creating);
}
data _null_;
make(foo) {
format a 4.;
creating...
a=today();
a=. _ERROR_=1 _N_=1
a='junk';
remove(foo) {
run;
}
%remove(&dat.);
}
%bloknote(CLOSE);
finalize() {
%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
Paul D Sherman
(408) 383 - 0471
sherman @ idiom.com
www.idiom.com / ~sherman / paul / pubs / macnotes
Further Study
• Try this at home
• Test with PROC's not DATA steps
• Call Execute calling macro which Call
Executes another macro which has errors