Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee !...
Transcript of Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee !...
Tips!&!Tricks!From!the!Committee!Peter!Stagg,!Decision!Informatics
It’s!possible!to!write!code!generated!by!macros!to!an!external!file.!
The!file!can’t!be!access!until!the!SAS!session!has!ended.
Use!the!options!MFILE!&!MPRINT.
Define!a!fileref for!MPRINT
eg.!filename!mprint 'c:\macro.sas'!;
Very!useful!for!complex!macros!with!many!loops!and!multiple!
ampersands!since!you!can!see!the!code!that!is!generated.
Debugging Complex Macros
Tips!&!Tricks!From!the!Committee!Peter!Stagg,!Decision!Informatics
Submit!this!line!of!code!to!properly!terminate!a!program!that!was!
submitted!with!unbalanced!quotes!or!missing!a!%mend!statement!in!a!
macro:
*';!*";!stop;!run;!quit;!%mend;
Correcting for unbalanced quotes and macro termination
Tips!&!Tricks!From!the!Committee!Bhupendra!Pant,!University!of!Western!Sydney
• PROC!FCMP provides!the!ability!to!build!your!own!functions!
and!call!sub"routines!using!the!DATA!Step!syntax!that!is!available!
in!the!data!step.!!
• PROC!FCMP!can!be!more!powerful!than!macros.
• Available!with!DATA!step!syntax!starting!with!SAS!9.2.
• PROC!FCMP!has!immense!potential!due!to!its!relative!ease!of!!
both!creating!the!required!code!and!using!the!procedure.
Tips!&!Tricks!From!the!CommitteeBhupendra!Pant,!University!of!Western!Sydney
BASIC!SYNTAX!using!PROC!FCMP:!declaring!function!and!subroutine
PROC!FCMP!Function name(argument!1,"...","argument!n);program!statements;return (expression);
endsub;
Subroutine name(argument!1,"...,"argument!n);outargs out!argument!1,"...,"out!argument!N;program!statements;return;
endsub;
Tips!&!Tricks!From!the!Committee!Bhupendra!Pant,!University!of!Western!Sydney
Simple!example!converting!Centigrade!to!Fahrenheit!
Tips!&!Tricks!From!the!Committee!Bhupendra!Pant,!University!of!Western!Sydney
Advantages!of!PROC!FCMP
Simplicity:!Complex!programming!can!be!simplified!by!“wrapping”!computations!into!PROC!FCMP!functions!and!call!routines.
Independence:!PROC!FCMP!“functions/CALL!routines”!are!independent!from!
their!use!i.e.!SAS!program!calling!a!function/routine!is!not!affected!by!the!implementation!of!the!function/routine.
Reusability:!A!library!of!reusable!functions!and!CALL!routines!can!be!built!using!DATA!step!that!can!be!reused!in!many!other!SAS!programs
Tips!&!Tricks!From!the!Committee!Bhupendra!Pant,!University!of!Western!Sydney
PROC!FCMP!is!a!relatively!simple!to!understand!procedure!for!both!
novice!and!advanced!SAS!users.!Easy!to!construct!with!immense!
potential.
• Very!useful if!there!is!complex!but!high!usage!program!that!can!be!
called!quickly!with!few!words!of!codes.!For!e.g.!mathematical!formula!
in!an!insurance!setting.
• Very!secure if!you!only!want!lower!level!users!to!have!read!only!
access!to!the!encapsulated!program.
• Very!convenient if!you!have!multiple!users!!simultaneously!!accessing!
the!program.
Tips!&!Tricks!From!the!Committee!Bhupendra!Pant,!University!of!Western!Sydney
Additional!Resources:
1. SAS!Documentation,!“The!FCMP!Procedure”,!http://support.sas.com/documentation/cdl/en/proc/61895/HTML/default/viewer.htm#a002890483.htm.
2. Eberhardt,!Peter,!2011,!“A!Cup!of!Coffee!and!Proc!FCMP:!I!Cannot!
Function!Without!Them”http://www.pharmasug.org/proceedings/2011/TU/PharmaSUG"2011"TU07.pdf
3. Secosky,!Jason,!“Executing!a!PROC!from!a!DATA!Step”,!http://support.sas.com/resources/papers/proceedings12/227"2012.pdf
Tips!&!Tricks!From!the!Committee!Paul!Mbatia,!Senior!Fraud!Analyst,!CBA
Finding!secret!SAS!options
You!can!find!out!the!settings!of!all!documented!and!undocumented!SAS!
options!by!using!the!following!code:
proc!options!internal;
run;
Tips!&!Tricks!From!the!Committee!Paul!Mbatia,!Senior!Fraud!Analyst,!CBA
! BELL!">!Enables/disables!the!warning!bell
! CDE=H! ">!Display!SAS!System!information
! CTRYDECIMALSEPARATOR=.! ">!Country!specific!decimal!number!separator
! CTRYTHOUSANDSEPARATOR=,!">!Country!specific!thousands!number!separator
! DEBUGLEVEL=!Controls!display!of!debug!information.!There!are!five!levels!(TESTING,!NORMAL,!DEBUG,!!
FULLDEBUG,!and!DEMO).
! ENHANCEDEDITOR! ">!Invoke!the!enhanced!editor!at!SAS!start!up
Some!of!the!options!that!are!revealed!include:
Tips!&!Tricks!From!the!Committee!Paul!Mbatia,!Senior!Fraud!Analyst,!CBA
Some!nice!stuff!on!the!web
! http://V8doc.sas.com/sashtml
! http://www2.sas.com/proceedings/sugi25/procced.pdf
! www.sashelp.com
! The!missing!semicolon!– www.sysseminar.com
! VIEWS!news!– www.views"uk.org
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
My!Three!Favourite SAS!Utility!Macros:
Macro!Name Description
PARMV A!parameter!validation!macro,!used!to!easily
validate!the!parameters!in!a!macro
SEPLIST A!macro!to!create!a!separated!(delimited)!list
LOOP A!macro!used!to!iterate!over!a!delimited!list,!
calling!a!child!macro!for!each!item!in!the!list
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
PARMV:
• Macro!parameter!validation!utility
• Originally!written!by!Tom!Hoffman!of!Hoffman!Consulting!
!I!have!permission!from!Tom!to!place!this!in!the!public!
domain
• Used!within!your!main!macro!to!validate!your!macro!
parameters
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
PARMV!(Cont):
• Available!parameter!validations!include:
! _VAL:!A!list!of!valid!values!or!the!word!POSITIVE!or!NONNEGATIVE
" VALUES!(Example)!=!YEAR!MONTH!DAY!(anything!else!is!rejected)
" POSITIVE!=!Positive!integer
" NONNEGATIVE!=!Positive!integer!or!Zero
" 0!or!1!=!Boolean!value:!
OFF!N!NO!F!FALSE!and!ON!Y!YES!T!TRUE!are!
aliases!for!0!or!1
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
PARMV!(Cont):
• Parameter!validations!include:
! _REQ:!Is!the!parameter!required?
! _WORDS:!Multiple!values!allowed?
! _CASE:!Convert!case!of!parameter!value?!(U/L/N)
! _VARCHK:!Check!that!variable!exists?!(globalize!variable)
! _DEF:!Default!value!when!not!assigned!by!calling!macro
! _MSG:!Display!a!message!in!the!SAS!log!and!set!
PARMERR=1
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
PARMV!(Cont):
• If!any!validations!fail!&PARMERR!is!set!to!1
• When!&PARMERR=1!%GOTO!%QUIT
• Example!Invocations:
%parmv(UNITS, _req=1,_words=0,_case=U,_val=Y YEAR M MONTH D DAY)
%parmv(WIDTH, _req=1,_words=0,_case=N,_val=POSITIVE)
%parmv(JUSTIFY,_req=1,_words=0,_case=U,_val=LEFT CENTER RIGHT)
%parmv(SCOPE, _req=0,_words=1,_case=U,_val=GLOBAL LOCAL AUTOMATIC)
%parmv(_MSG=&data data set or view does not exist) (sets PARMERR=1)
%if (&parmerr) %then %goto quit;
%quit: %mend;
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
SEPLIST:
• Emit!a!list!of!words!separated!by!a!delimiter
• Originally!written!by!Richard!Devenezia
! This!macro!is!already!in!the!public!domain!http://www.devenezia.com/downloads/sas/macros/index.php?m=seplist!
! I!also!have!permission!from!Richard!to!present!this!macro
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
SEPLIST!(Cont):
• Parameters!include:
! ITEMS:!Input!list!of!items
! INDLM:!Input!delimiter!(default!=!space)
! DLM:!Output!delimiter!(default!=!comma)
! PREFIX:!String!to!place!before!each!item
! NEST:!Quote!each!item!(‘!‘,!“!“,!(!),!{!},![!])
! SUFFIX:!String!to!place!after!each!item
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
SEPLIST!(Cont):
• Placing!commas!in!a!macro!variable!list!opens!you!up!to!a!
world!of!headaches!(macro!quoting!and!parsing!issues)
• Instead,!add!the!commas!at!“runtime”!with!%seplist
• %seplist is!also!especially!useful!to!switch!between!data!step!
and!SQL!syntax
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
SEPLIST!(Cont):
• Example!Invocations:
Invocation Results
%put!%seplist(foo bar!blah); foo,bar,blah
%put!%seplist(a list!^!of!words,!indlm=^); a!list,of words
%put!IN (%seplist(foo bar!blah,!nest=qq)); IN!(“foo”,”bar”,”blah”)
%put!%seplist(a!b!c,prefix=t1.); t1.a,t1.b,t1.c
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
SEPLIST!(Cont):
• A!more!complex!example:proc sql;
create table test as
select
%seplist(var1 var2 var3,prefix=t1.),
%seplist(var4 var5 var6,prefix=t2.)
from
table1 t1, table2 t2
where
t1.var1=t2.var2
and
t1.var2 in (%seplist(foo bar blah,nest=qq))
;
quit;
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
LOOP:
• Loop!over!a!delimited!list,!calling!a!child!macro!for!each!token!
(“word”)!in!the!list
• Nothing!special!about!parsing!a!list!of!words
• However,!pulling!the!looping!code!into!a!separate!macro,!
which!calls!a!child!macro!that!you!define!at!“run!time”,!allows!
you!to!“think!differently”
• On!very,!very!rare!occasions,!you!may!have!a!larger!list!than!
will!fit!in!a!single!macro!variable.
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
LOOP!(Cont):
• Parameters!include:
! LIST:!Input!list!of!items
! DLM:!Input!delimiter!(default!=!space)
! MNAME:!Child!macro!to!call!for!each!word
(default!=!%code)
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
LOOP!(Cont):
• Example!Invocations:
%macro code;
%put &word;
%mend;%loop(hello world);
Result in SAS log:
hello
world
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
LOOP!(Cont):
• Example!Invocations!(cont):
%macro rename;
&word=_&word
%mend;
proc contents data=sashelp.class out=contents;
run;
proc sql noprint;
select name into :vars separated by "^" from contents order by varnum;
quit;
data test;
set sashelp.class;
rename %loop(&vars,dlm=^,mname=rename);run;
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
LOOP!(Cont):
• Example!Invocations!(cont):
%macro print; /* use two delimiters for "multidimensional array" */
%let data =%scan(&word,1,|);
%let vars =%scan(&word,2,|);
%let where=%scan(&word,3,|);
title "Printing &data";
proc print data=&data;
where &where;
var &vars;
run;
%mend;
%loop(
sashelp.cars | Make Model Type EngineSize Horsepower | Make in ("Audi","BMW","Porsche")
^ sashelp.class | _all_ | 1
^ sashelp.stocks | Stock Date Open Close | Close > 100
,dlm=^,mname=print
);
Tips!&!Tricks!From!the!Committee!Scott!Bass,!Senior!Information!Analyst,!Bupa
Download!Macros:
• All!these!(and!many!more)!macros!are!available!for!download:
! https://github.com/scottbass/SAS/tree/master/Macro
! https://github.com/scottbass/SAS/blob/master/Macro/parmv.sas
! https://github.com/scottbass/SAS/blob/master/Macro/seplist.sas
! https://github.com/scottbass/SAS/blob/master/Macro/loop.sas