Date: Tue, 10 Nov 1998 11:41:08 -0500
Reply-To: WHITLOI1 <WHITLOI1@WESTAT.COM>
Sender: "SAS(r) Discussion" <SAS-L@UGA.CC.UGA.EDU>
From: WHITLOI1 <WHITLOI1@WESTAT.COM>
Subject: Re: Can do this by 'one step' ?
Content-Type: text/plain; charset=US-ASCII
Subject: Can do this by 'one step' ?
Summary: In one macro invocation, yes. A simple and then a user
friendly solution is given.
Respondent: Ian Whitlock <whitloi1@westat.com>
Chenglong Han <hanc@CALIB.COM> asks:
> I want to invoke a sas macro, for example, MABC, for multiple
> times. Can I do this just by invoking once ? For example,
>
> %MACRO MABC ( VAR); ....... %MEND;
>
> Instead of doing this by %MABC ( X1); %MABC (X2); ....... %MABC
> (Xn);
>
> Can I do this by some way like %MABC (X1-XN);
One, could easily achieve the objective by changing the parameter
list. For example:
%macro mabc ( var= ) ;
%put macro mabc exectuing with var=&var ;
%mend mabc ;
%macro drvrmabc ( root= , strt= , stop= ) ;
%local i ;
%if %quote(&stop) = %str() %then %let stop = &strt ;
%do i = &strt %to &stop ;
%mabc ( var = &root&i )
%end ;
%mend drvrmabc ;
%drvrmabc ( root=xyz12a, strt=43 )
%drvrmabc ( root=xyz12a, strt=43, stop=45 )
Of course, one could replace the call to %MABC in the macro DRVRMABC
with the code of MABC and then change the name of the macro to MABC,
if desired. Note DRVRMABC is callable anywhere MABC is.
I interpreted the question as a more interesting one. Can one preserve
the parameter and notation as asked for? Again I have used a separate
driving macro and a key word parameter. (I don't write macros with
positional parameters except in unusual circumstances.) Here is the
code. It demonstrates a big advantage given by the ability to execute
DATA step functions within macro.
%macro drvrmabc ( var= x1 - x5 ) ;
%local temp strt stop root1 root2 i x ;
%let temp = %scan(&var, 1 , - ) ;
%let temp = %sysfunc(reverse(&temp)) ;
%let x = %sysfunc(verify(&temp,0123456789)) ;
%let strt = %sysfunc(reverse(%substr(&temp,1,&x-1))) ;
%let root1 = %sysfunc(reverse(%substr(&temp,&x))) ;
%let temp = %scan(&var, 2 , - ) ;
%if %quote(&temp) = %str() %then
%do ;
%let stop = &strt ;
%let root2 = &root1 ;
%end ;
%else
%do ;
%let temp = %sysfunc(reverse(&temp)) ;
%let x = %sysfunc(verify(&temp,0123456789)) ;
%let stop = %sysfunc(reverse(%substr(&temp,1,&x-1))) ;
%let root2 = %sysfunc(reverse(%substr(&temp,&x))) ;
%end ;
%if &root1 = &root2 and &strt <= &stop %then
%do ;
%do i = &strt %to &stop ;
%mabc ( var = &root1&i )
%end ;
%end ;
%else
%do ;
%put ERROR(drvr): Cannot parse, halting. VAR=&var ;
%end;
%mend drvrmabc ;
%drvrmabc ( var=xyz12a43 )
%drvrmabc ( var=xyz12a43-xyz12a45 )
%drvrmabc ( var=xyz12a43-xy12a45 )
Again the driving macro may be called anywhere the original macro can
be called. The code is a good deal harder, but this is the price of
friendliness.
None of the above assumes one is in a DATA step and VAR names a
variable or group of variables in a SAS data set. If this is the case
then one could have the driver
%macro drvrmabc ( data = &syslast , var=a -- b c1 - c5 d ) ;
The code for the driver now gets a good deal more difficult to do
correctly, and I will not present it. However, I am interested in
pursuing the question of whether the parameter DATA can be eliminated.
Does anyone know of a method of finding out what data sets have been
opened in compiling a DATA step so that the DATA parameter would be
superfluous? Then, of course, I would also like access to the PDV,
but I am certain this is not yet possible.
Ian Whitlock