Debugging Complex Macros 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 filereffor 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.
Peter Stagg, Decision Informatics Correcting for unbalanced quotes and macro termination 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;
Bhupendra Pant, University of Western Sydney PROC FCMPprovides 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 Committee Bhupendra Pant, University of Western Sydney BASIC SYNTAX using PROC FCMP: declaring function and subroutine PROC FCMP Functionname(argument 1,..., argument n); program statements; return(expression); endsub; Subroutinename(argument 1,..., argument n); outargsout argument 1,..., out argument N; program statements; return; endsub;
Bhupendra Pant, University of Western Sydney Simple example converting Centigrade to Fahrenheit
Advantages of PROC FCMP Bhupendra Pant, University of Western Sydney 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
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 usefulif 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 secureif you only want lower level users to have read only access to the encapsulated program. Very convenientif you have multiple users simultaneously accessing the program.
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
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;
BELL > Enables/disables the warning bell CDE=H > Display SAS System information CTRYDECIMALSEPARATOR=. > Country specific decimal number separator Paul Mbatia, Senior Fraud Analyst, CBA Some of the options that are revealed include: 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 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 Paul Mbatia, Senior Fraud Analyst, CBA
My Three FavouriteSAS Utility Macros: Macro Name Description PARMV SEPLIST LOOP A parameter validation macro, used to easily validate the parameters in a macro A macro to create a separated (delimited) list A macro used to iterate over a delimited list, calling a child macro for each item in the list
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
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
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
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;
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
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
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 %seplistis also especially useful to switch between data step and SQL syntax
SEPLIST (Cont): Example Invocations: Invocation Results %put %seplist(foobar blah); foo,bar,blah %put %seplist(alist ^ of words, indlm=^); a list,ofwords %put IN(%seplist(foobar blah, nest=qq)); IN ( foo, bar, blah ) %put %seplist(a b c,prefix=t1.); t1.a,t1.b,t1.c
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;
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.
LOOP (Cont): Parameters include: LIST: Input list of items DLM: Input delimiter (default = space) MNAME: Child macro to call for each word (default = %code)
LOOP (Cont): Example Invocations: %macro code; %put &word; %mend; %loop(hello world); Result in SAS log: hello world
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;
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 );
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