无法在通话中重新启动宏

时间:2017-12-04 17:19:08

标签: sas sas-macro

我在数据步骤中调用用户定义的宏。宏包含一个do循环,我想将do循环的i计数器的值赋给我正在使用调用symput的宏变量。请在下面找到我的代码。你能告诉我哪里出错了。

%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 个答案:

答案 0 :(得分:1)

您正在混合宏代码和数据步骤代码。宏变量引用的值(如&yr.&&int_rt_&yr.)在数据步骤编译之前和DO循环运行之前很久就会被评估。

如果要在数据步骤中创建一堆变量,请使用ARRAY。然后,您可以使用I索引数组。

要创建宏,您需要从使用SAS代码开始。然后你可以尝试制作一个宏,为你生成不同版本的代码。

答案 1 :(得分:0)

如果你真的希望输出数据集有23个新变量,如

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

并且您不想使用数组,将宏代码更改为在宏中循环,而不是在DATA Step中。所以

do i=

会变成

%do i=

并将原始匹配end更改为%end

在此更改之后,宏将生成一些“壁纸”数据步骤源代码,用于执行公式。

代码构造就在那条细线上,没有经验的编码器可能会尝试在宏变量i中处理年份,就像它是一个DATA Step变量一样。

建议始终能够在普通的DATA Step中编写解决方案,然后您可以通过在普通代码中抽象和参数化显着特征和模式来宏观化概念。