0
votes

I am calling a user defined macro within a data step. The macro contains a do loop and I would like to assign the value of i counter of the do loop to a macro variable for which I am using a call symput. please find my code below. Can you tell me where I am going wrong.

%let RedressStartYear=2007;
%let RedressEndDate= '31OCT2017'D;

*Yearly Interest Rate;
%let int_rt_2007= '0.0421';
%let int_rt_2008= '0.0421';
%let int_rt_2009= '0.0421';
%let int_rt_2010= '0.0421';
%let int_rt_2011= '0.0421';
%let int_rt_2012= '0.0419';
%let int_rt_2013= '0.0429';
%let int_rt_2014= '0.0430';
%let int_rt_2015= '0.0401';
%let int_rt_2016= '0.0378';
%let int_rt_2017= '0.0358';


Data Redress_Data;
format BilledMonth date9.;
BilledMonth='01MAR2013'D;
BilledYear=Year(BilledMonth);
Customer='ABC Ltd.';
OverChargeAmt=34.6656;
run;

%macro Calculate_CI(billmon, Amt,Payday);

CI_AMT=0;

do i=&RedressStartYear. to year(&payday.) by 1;

*The value of i not getting resolved and getting assigned to the macro variable yr;
Call symput ('yr',i);

    if i<year(&billmon.) then CI_AMT= CI_AMT+0;

    if i=Year(&billmon.) then do;

        No_days_Int_&yr.=intck('day',&billmon.,MDY(12,31,i))+1;
        Days_in_Year_&yr.=intck('day',MDY(01,01,i),MDY(12,31,i))+1;
        CI_AMT= CI_AMT+ (&&int_rt_&yr.* No_days_Int_&yr. * &Amt.)/Days_in_Year_&yr.; end;

    if i>Year(&billmon.) and Year(&billmon.)< Year(&Payday.) then CI_AMT=CI_AMT + (&&int_rt_&yr. * &Amt.);

    if i=Year(&Payday.) then do;
        No_days_Int_&yr.=intck('day',MDY(01,01,i),&Payday.)+1;
        Days_in_Year_&yr.=intck('day',MDY(01,01,i),MDY(12,31,i))+1;
        CI_AMT=CI_AMT+ (&&int_rt_&yr. * No_days_Int_&yr. * &Amt.)/Days_in_Year_&yr. ; end;

end;

%mend Calculate_CI;

Data Redress_Data_CI;
set Redress_Data;
    %Calculate_CI(BilledMonth, OverChargeAmt,&RedressEndDate.);
run;
2
Look up CALL EXECUTE which is how you call a macro from a data step.Reeza

2 Answers

1
votes

You are mixing macro code and data step code. The value of the macro variable references (like &yr. and &&int_rt_&yr.) are evaluated before the data step is compiled and long before the DO loop runs.

If you want to create a bunch of variables in a data step then use an ARRAY. You can then use I to index into the array.

To create a macro you need to start with working SAS code. Then you can try to make a macro that will generate different versions of that code for you.

0
votes

If you truly want the output data set to have 23 new variables, as in

  • No_days_Int_2007
  • Days_in_Year_2007
  • ...
  • No_days_Int_2017
  • Days_in_Year_2017
  • CI_AMT

And you don't want to use arrays, change your macro code to loop in macro, not in DATA Step. So

do i=

would become

%do i=

And change the original matching end to %end.

After this change the macro will generate some 'wallpaper' DATA Step source code that does your formulas.

The code construct is on that fine line where inexperienced coders might attempt to deal with the year in the macro variable i as if it were a DATA Step variable.

Advice is always to be able to code a solution in plain DATA Step first, then you can macroize the concept by abstracting and parameterizing salient features and patterns in the plain code.