Macro MloopsX
From sasCommunity
SUGI31.012
http://www2.sas.com/proceedings/sugi31/012-31.pdf
[edit] List Processing - Make Light Work of List Processing in SASĀ®
Peter Crawford, Crawford Software Consultancy Limited
ABSTRACT
In the world of extensive metadata, list processing prevails. A small utility macro has improved applications development (source and maintenance) where they handle lists. This paper demonstrates techniques. Over a period of 4 years, this macro has been refined into a robust and reliable facility that enables applications to delegate most list processing and leave cleaner, clearer code that will be cheaper to build and maintain.
/* Program : mloopsx.sas *
* -------------------------------------------------------------------- *
* Purpose : List processing: for each element of a list *
* : call a macro *
* : without going through the statement boundary
* -------------------------------------------------------------------- *
* Author : Peter Crawford - Crawford Software Consultancy Limited *
* Version : 2.1 *
* Created : 14.10.02 *
* published in: http://www2.sas.com/proceedings/sugi31/012-31.pdf
* -------------------------------------------------------------------- *
* Modification History *
* Peter Crawford 14.10.02 *
* prefix local macro vars with macro name, to avoid contention with any*
* macro vars inherited by the macro called *
* Peter Crawford 20.02.04 *
* apply %superQ() to macro vars in tests, to avoid arithmetic in *
* implicit %eval() *
* 13/02/2005 superQ on testing for empty execut= *
* ------------------------------------------------------------------- */
%MACRO mLoopsX
(execut = /* name of macro to invoke */
,with = /* delimited list of calls */
,withdlm = %str( ) /* list delimiter */
) / des='execute a macro for each word in a list' ;
/* examples:
suppose you have a macro like
%macro syk( op );
%sysfunc( getoption( &op,keyword ) )
%mend syk ;
then
%put oldops = %mloopsx( execut= syk, with=mprint mlogic symbolgen);
loads re-usable settings for these system options
The macro can operate on larger scale as a statement like
%mloopsx( execut=main_process, with= London New-York Tokyo )
****************************************/
%if %superQ(execut) eq
or %superQ(with) eq %then %goto mParmError ;
%local mloopsx_i mloopsx_j ;
%let mloopsx_i = 1 ;
%let mloopsx_j = %scan( &with, &mloopsx_i, &withdlm );
%do %until( %superQ(mloopsx_j) eq ) ;
%&execut.( &mloopsx_j )
%let mloopsx_i = %eval( &mloopsx_i +1 );
%let mloopsx_j = %scan( &with, &mloopsx_i, &withdlm );
%end ;
%goto mExit;
%mParmError:
%put mLoopsX-Error need parameters, got execut=&execut and with=&with;
%mExit:
%mend mLoopsX ;
%MACRO syk(option) / des = 'collect option value with keyword';
%sysfunc(getoption(&Option,keyword)%mend syk ;
/*********************************************************************
* program : months_set.sas *
* version : 0.1 *
*--------------:-----------------------------------------------------*
* originator : Peter Crawford, Crawford Software Consultancy Ltd *
*--------------:-----------------------------------------------------*
* description : loop over date range replacing a pattern with MONYY *
*--------------:-----------------------------------------------------*
* outputs : text *
*--------------:-----------------------------------------------------*
* change hist. : opened 22/12/2005 and tested ! *
*--------------:-----------------------------------------------------*
* dd/mm/yyyy : *
*********************************************************************/
%MACRO months_set
( string = /* pattern to repeat over dates */
, seek = ##### /* string to be replaced */
, from = JAN04 /* dates in valid monyy style */
, to = &last_mon /* ending date */
, looplimit = 100 /* used to avoid over-running */
)/ des = '?';
%do %while( %sysevalf( "1&from"d LE "1&to"d ) ) ;
%sysfunc( tranwrd( &string, &seek, &from ))
%let from = %sysfunc( intnx( month, "1&from"d, 1 ), MONYY5);
%let looplimit = %eval( &looplimit - 1 );
%if &looplimit < 1 %then %goto Mexit ;
%end;
%Mexit:
%MEND months_set ;
