SAS%如果是其他宏

时间:2018-06-14 10:43:03

标签: if-statement macros sas

我只有宏%IF%ELSE的问题。 我必须设置开关" Y"或" N" (更多将来)这个变量运行不同的代码部分。 例如:

data REKORD_RACH;
   input id_wsadu dept $;
   datalines;
1 Sales
2 Acctng
3 eeeaa
4 ffff
;
%LET Czy_Max = 'Y'; /*<=============================== SWITCH*/
OPTION MPRINT;
option compress=yes validvarname=any;

%macro Set_id_wsadu(Czy_Max);
   %if &Czy_Max. = 'N' %then
      %do;
        %let id_wsadu = 3;/*Tu wpisujemy ręcznie id wsadu które nas interesuje*/
    %end;

   %else %if &Czy_Max. = 'Y' %then
      %do;
            Proc SQL NOPRINT;
            Select MAX(id_wsadu) Into :id_wsadu
            From Work.REKORD_RACH;
            quit;
      %end;
%mend;
%Set_id_wsadu;

%put &id_wsadu;

PROC SQL;
   CREATE TABLE REKORD_RACH_GET AS 
   SELECT *
   FROM REKORD_RACH
   WHERE ID_WSADU = &id_wsadu
;QUIT;

但是Sas指南向我展示了这些日志:

54         %mend;
55         %Set_id_wsadu;
56         
57         %put &id_wsadu;
WARNING: Apparent symbolic reference ID_WSADU not resolved.
&id_wsadu

我应该怎么做才能让它发挥作用?

2 个答案:

答案 0 :(得分:2)

首先,您需要将%global id_wsadu;添加到宏中。这将使宏值在宏外部解析。然后,您需要通过传递参数,例如%Set_id_wsadu('Y')来正确调用您的宏。这里:

%macro Set_id_wsadu(Czy_Max);
%global id_wsadu;
   %if &Czy_Max. = 'N' %then
      %do;
        %let id_wsadu = 3;/*Tu wpisujemy ręcznie id wsadu które nas interesuje*/
    %end;

   %else %if &Czy_Max. = 'Y' %then
      %do;
            Proc SQL NOPRINT;
            Select MAX(id_wsadu) Into :id_wsadu
            From Work.REKORD_RACH;
            quit;
      %end;
%mend;
%Set_id_wsadu('Y');

%put &id_wsadu;

PROC SQL;
   CREATE TABLE REKORD_RACH_GET AS 
   SELECT *
   FROM REKORD_RACH
   WHERE ID_WSADU = &id_wsadu.;
QUIT;

答案 1 :(得分:2)

您遇到宏变量范围问题以及宏变量值的混淆。

首先,您定义了一个全局宏变量(因为您在任何特定宏范围之外运行了%let)。

%LET Czy_Max = 'Y'; 

然后,您定义了一个使用相同宏变量名称作为参数的宏。

%macro Set_id_wsadu(Czy_Max);

这将创建一个名为Czy_Max的本地宏变量,该变量将隐藏具有相同名称的全局宏变量的值。您可以通过在调用时将全局宏变量的值传递到宏中来使此设置工作。像这样:

%Set_id_wsadu(&Czy_Max);

虽然为全局和本地宏变量使用不同的名称可能不那么令人困惑。

其次,您要为宏内部的宏变量设置一个值,而没有明确定义SAS是否应该将该宏变量视为本地或全局。

%let id_wsadu = 3;

如果该变量运行时宏变量id_wsadu已存在,则其值将更新。否则,它将导致创建一个本地宏变量,该宏将在宏完成运行时停止存在。您可以通过确保在调用宏之前定义宏变量来解决此问题。

%let id_wsadu = ;
%Set_id_wsadu(&Czy_Max);

或者您可以在宏中添加%global语句,以在为其分配值之前在全局符号表中定义宏变量。但是,如果从另一个已经将该宏变量创建为本地的宏调用此宏,则会导致问题。您不能使用与现有本地宏变量同名的新全局宏变量。为了防止该错误,您可以在将宏变量设置为全局之前测试该宏变量是否已存在。像这样:

%if not %symexist(id_wsadu) %then %global id_wsadu;

最后,为什么要在宏变量的值中添加引号?看起来你一直这样做,所以代码应该工作,但这可能意味着你不明白引号实际上是宏变量值的一部分。这与需要引号的SAS代码不同,因此编译器知道字符串文字,数字文字和变量名称或SAS关键字之间的区别。因此,在SAS代码中,文字周围的引号不是值的一部分。

因此,在数据步骤中,您可以使用不同的外部引号运行这样的代码,文字将匹配。

if 'A' = "A" then

但是在宏代码中,引号是值的一部分,所以如果你尝试了这段代码:

%if 'A' = "A" %then 

这两个值不同,因为'不等于"