2017-05-03 83 views
0

我是SAS宏写入的新手,我一直在为以下实例编写代码而苦苦挣扎。SAS:if循环中变量的定义

%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循环中指定的变量。有没有办法改变代码,以使报表日期变量符合DateOfInterest?

谢谢。

回答

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让它们在全球范围内可用。

+0

嗨。非常感谢您的回应。我不确定是否正确理解了%全局公式。但是,即使我使用上面提供的样本,报告日期也会采用最后一个循环中定义的值(%put&reportdate =&reportdate2 =&reportdate3 =; “31DEC2016”d =“01JAN2017”d =“01OCT2016”d =)。我不明白为什么报告日没有遵循正确的循环,只是采取最后的可能值。你能帮我解决这个问题吗? – FioravanteL