12-24-2014 02:36 PM
i want to create a macro that takes current date and number of loopback months as input and create a series of macro variables capturing last day of each month
number of look back months (n) =6
The output should be (6 statements to create 6 variable names)
12-24-2014 02:42 PM
Use a data _null_ step with call symput instead:
data test; *creating a data set for debugging purposes but can be changed to _null_ so no dataset is created;
do i=1 to &nmonths;
var_name=catx("_", date, i);
var_value=put(intnx('month', &curr_dt, i, e), yymmddn8.);
call symput(var_name, var_value);
12-24-2014 02:59 PM
%local i inpdte;
%do i=1 %to &n.;
%let date_&i.=%sysfunc(intnx(month, &inpdte., %eval(&i.*-1), e),yymmddn8.);
12-24-2014 02:59 PM
I want to get the %let statement as I will be using these later.
When I use a do loop to get the %let statements, it does not recognize the ampersand in the variable name and in the sysfunc statement
I was wondering if you can think of any other technique that will produce the % let statements
12-24-2014 09:09 PM
May be you should give us the bigger picture especially why you want these %let statements generated explicitly so that we can propose an appropriate solution.
If it's really about dynamically generating code then one way to go is a "data _null_" step with put statements where you generate the code and write it to an external file. You then can %include this file so that the generated code inside gets executed.
12-26-2014 10:33 AM
Not sure why you need so many macro variables. Personally I do not like the idea of macro "arrays" as I find that most programs are easier to maintain if you use a different coding pattern.
The problem with using a macro to generate macro variables that you want to use later is that by default the macro variables are defined in the scope of the sub-macro and so disappear when it ends. One way to deal with this is to force the macros to be made in the GLOBAL macro scope as others have posted above. This can cause trouble with other parts of your code that might want to use those same macro variable names for some other meaning. Here are two methods to allow you define the new macros in the current macro scope (not the scope of the sub macro and not necessarily the GLOBAL scope either).
1) Is to take advantage of a feature of the fact that if a sub macro does not have any macro variables at all then it will not generate a new macro scope. Note that this means that the macro cannot take any parameters either. So your number of months will have to placed into another macro variable first before calling the new macro.
do i=1 to input(symget('months'),comma32.);
%mend lookback ;
2) Another method is to have the macro return the text of the %LET statements (without actually running) them as quoted macro text. And then use %UNQUOTE() to execute the %LET statements in the calling environment. This will let you define the macro with parameters and local macro variables.
%local i str;
%if ^%length(&start) %then %let start=%sysfunc(today());
%do i=1 %to &months ;
%let str=&str.%nrstr(%let )date_&i=%sysfunc(intnx(month,&start,-&i,e),yymmddn8.)%nrstr(;