tips tricks from the committee - sas groups...tips !&!tricks !from !the !committee !...

27
Tips&TricksFromtheCommittee PeterStagg,DecisionInformatics It’spossibletowritecodegeneratedbymacrostoanexternalfile. Thefilecan’tbeaccessuntiltheSASsessionhasended. UsetheoptionsMFILE&MPRINT. Defineafileref forMPRINT eg.filenamemprint 'c:\macro.sas'; Veryusefulforcomplexmacroswithmanyloopsandmultiple ampersandssinceyoucanseethecodethatisgenerated. Debugging Complex Macros

Upload: others

Post on 11-Jul-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 2: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 3: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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.

Page 4: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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;

Page 5: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

Tips!&!Tricks!From!the!Committee!Bhupendra!Pant,!University!of!Western!Sydney

Simple!example!converting!Centigrade!to!Fahrenheit!

Page 6: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 7: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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.

Page 8: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 9: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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;

Page 10: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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:

Page 11: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 12: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 13: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 14: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 15: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 16: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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;

Page 17: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 18: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 19: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 20: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 21: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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;

Page 22: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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.

Page 23: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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)

Page 24: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

Page 25: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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;

Page 26: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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

);

Page 27: Tips Tricks From the Committee - SAS Groups...Tips !&!Tricks !From !the !Committee ! Peter!Stagg,!Decision !Informatics It’s !possible !to !write !code !generated !by !macros !to

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