我是SAS宏写作的新手,我一直在努力为以下实例编写代码。
%let DateOfInterest= "15jul2016"d;
%let yearyyyy=%sysfunc(putn(&DateOfInterest,year4.));
%let yearyyyy2=eval(yearyyyy+1);
data _null_;
if "01JAN2016"d<=&DateOfInterest<="31MAR2016"d then do;
%let reportdate="31MAR2016"d;
%let reportdate2="01APR2016"d;
%let reportdate3="01JAN2016"d;
%let QuarterOfInterest=Q1;
if "31MAR2016"d<&DateOfInterest<="30JUN2016"d then do;
%let reportdate="30JUN2016"d;
%let reportdate2="01JUL2016"d;
%let reportdate3="01APR2016"d;
%let QuarterOfInterest=Q2;
if "30JUN2016"d<&DateOfInterest<="30SEP2016"d then do;
%let reportdate="30SEP2016"d;
%let reportdate2="01OCT2016"d;
%let reportdate3="01JUL2016"d;
%let QuarterOfInterest=Q3;
if "30SEP2016"d<&DateOfInterest<="31DEC2016"d then do;
%let reportdate="31DEC2016"d;
%let reportdate2="01JAN2017"d;
%let reportdate3="01OCT2016"d;
%let QuarterOfInterest=Q4;
end;
end;
end;
end;
run;
代码运行没有任何问题。但是,无论我选择哪个DateOfInterest,reportdate变量都是最后一个if循环中指定的变量。有没有办法改变代码,以使reportdates变量符合DateOfInterest?
感谢。
答案 0 :(得分:1)
您以一种不起作用的方式将宏与数据步骤相结合。宏语言和数据步骤语言基本无关:宏语言可以写入数据步骤代码,反之亦然,但一般不会相互影响。
特别是,在打开任何数据集或编译或执行任何数据步骤代码之前,首先编译和执行宏代码。这真的很重要 - 它可以让你编写datastep代码预编译。
所以
if ... then do;
%let something
end;
这不起作用,因为首先发生宏%,然后发生数据步骤。
%if ... %then %do;
%let something
%end;
这是有效的,因为它都是宏语言。一般来说,如果它一开始没有%
,它就不是宏语句/函数,并且不会使用宏语言。
然而,你正在做的事情会有更多的复杂情况。你必须在宏中使用%if
,但你也有范围问题。
所以像这样的一般小宏将是:
%let mval=1;
%macro set_things;
%if &mval=1 %then %do;
%let mval1=1;
%end;
%else %if &mval=2 %then %do;
%let mval2=1;
%end;
%else %do;
%let mval0=1;
%end;
%mend;
%set_things();
%put &=mval &=mval0 &=mval1 &=mval2;
请注意,它不起作用:因为它不是全局的,所以你需要在宏中再添一行:
%global mval0 mval1 mval2;
告诉SAS让它们在全球范围内可用。