Date: Thu, 25 Sep 2003 16:56:07 -0400
Reply-To: Ian Whitlock <WHITLOI1@WESTAT.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Ian Whitlock <WHITLOI1@WESTAT.COM>
Subject: Re: Nested macro question for mavens and gurus
Content-Type: text/plain
Doug,
I would simplify and speed things up with SAS dates. Following Dennis'
suggestion and using
%macro loop_through_months(startmon=, endmon=, sas_code_to_loop=);
%local mon ;
%do mon = %sysfunc(inputn(01&startmon,date9.))
%to %sysfunc(inputn(01&endmon,date9.)) ;
%unquote (&sas_code_to_loop)(mon=&mon)
%let mon = %sysfunc(intnx(month,&mon,0,e)) ;
%end;
%mend loop_through_months;
%macro test_macro(mon=);
%put ====> test_macro executing,
curr_yyyymm=%sysfunc(putn(&mon,yymmn6.)) ;
%mend test_macro ;
%loop_through_months(startmon=dec2002,
endmon=feb2003,
sas_code_to_loop=%nrstr(%test_macro))
Some comments are in order. With all those function calls, is it really
faster? Yes functions have been implemented very efficiently in comparison
with macro code. Why use the end of the month in the incrementation?
Because the iterative loop will add 1 bringing the date to the first of the
month. Why not use %BY 0? Because some Institute programmer checks your
code and refuses to allow %BY 0.
Should one have the hidden parameter MON? It is questionable. It could be
left out, but my conscience won't let me call macros without passing
parameters. Why didn't I simply make the call
%loop_through_months(startmon=dec2002,
endmon=feb2003,
sas_code_to_loop=%nrstr(%test_macro(mon=&mon))
I didn't want to burden your call with my conscience. Actually this form
may casue more problems than it is worth. I probably would change the call
the design to
%macro loop_through_months(x= ,startmon=, endmon=, sas_code_to_loop=);
%local &x ;
%do &x = %sysfunc(inputn(01&startmon,date9.))
%to %sysfunc(inputn(01&endmon,date9.)) ;
%unquote (&sas_code_to_loop)
%let &x = %sysfunc(intnx(month,&&&x,0,e)) ;
%end;
%mend loop_through_months;
%macro test_macro (mon=mon);
%put ====> test_macro executing,
curr_yyyymm=%sysfunc(putn(&mon,yymmn6.)) ;
%mend test_macro ;
options nomlogic;
%loop_through_months(x=mon,
startmon=dec2002,
endmon=feb2003,
sas_code_to_loop=%nrstr(%test_macro(mon=&mon)))
Here the parameter, X, allows the user to name the index and then to pass
the required value. Is it worth it? I still am not sure, but it allows the
user to name the index and to pass the value of that index as a parameter.
IanWhitlock@westat.com
-----Original Message-----
From: Doug Zirbel [mailto:doug_zirbel@HOTMAIL.COM]
Sent: Wednesday, September 24, 2003 12:56 PM
To: SAS-L@LISTSERV.UGA.EDU
Subject: Nested macro question for mavens and gurus
I wrote a macro which loops through "months", each iteration incrementing a
YYYYMM macro variable by 1 month. I want to pass that &YYYYMM to another
macro nested within the loop, but it of course is not cooperating.
So how do I pass a macro variable created with a %LET to a macro as its
macro parameter?
Here's the code:
options nocenter mprint mlogic;
%global curr_yyyymm;
%let curr_yyyymm=;
/*******************************************/
/* This is the test macro (with a parameter) to
/* be nested into the macro loop in the next
/* macro.
/*******************************************/
%macro test_macro;
%put ====> test_macro executing, curr_yyyymm=&curr_yyyymm; %mend;
/*******************************************************/
/* This is the macro that loops through
/* "months" creating a new macro var "curr_yyyymm"
/* which is incremented by 1 month each iteration.
/* Right after it is incremented, it is to pass
/* that macro var to the nested macro.
/*******************************************************/
%macro loop_through_months(start_yyyymm=, end_yyyymm=, sas_code_to_loop=);
%let curr_yyyymm = &start_yyyymm;
/**********************************************
/* Loop, from starting YYYYMM to ending YYYYMM
/* incrementing at the bottom. "DO UNTIL"
/* does its T/F test at the bottom of the loop.
/**********************************************/
%do %until (&curr_yyyymm > &end_yyyymm);
%put curr_yyyymm=&curr_yyyymm;
/*******************************************/
/* This macro var holds the test_macro to be
/* passed to the loop and to then be
/* executed before the next loop interation.
/*******************************************/
&&sas_code_to_loop;
/*******************************************/
/* Increment from December (12) to January (01)
/* if necessary after calling nested macro
/*******************************************/
%if %substr(&curr_yyyymm,5,2) = 12 %then %do;
%let curr_yyyy=%eval(%substr(&curr_yyyymm,1,4) + 1);
%let curr_mm = 01;
%let curr_yyyymm=&curr_yyyy.&curr_mm;
%end;
/*******************************************/
/* Increment from one month # to the next #
/* after calling nested macro
/*******************************************/
%else %do;
%let curr_yyyymm=%eval(&curr_yyyymm + 1);
%end;
%end;
%mend loop_through_months;
%loop_through_months(start_yyyymm=200212,
end_yyyymm=200302,
sas_code_to_loop=%test_macro);