Macro MloopsX

From sasCommunity
Jump to: navigation, search

SUGI31.012

http://www2.sas.com/proceedings/sugi31/012-31.pdf


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 ;