我可以从宏变量创建宏名称吗

Can I Create a Macro Name from a Macro Variable

我想使用 INTO 函数将一组值发送到宏中。我一直这样做。但是,我想对三个不同的表做同样的事情,我想用我传入的宏变量创建 INTO 宏名称。可以这样做吗?这对我不起作用。也许我需要在宏名称之前添加一个命令来先编译它?本质上,我想要创建三个宏存储:IPCOLS 的值来自 IP_DENOMINATORS,LTCOLS 的值来自 LT_DENOMINATORS,OTCOLS 的值来自 OT_DENOMINATORS.

Proc Sql noprint;
%macro SUBST() / parmbuff; 
%let i=1;
%let FT=%scan(%bquote(&SYSPBUFF),1);  

%do %while (&FT^=); 
Select DISTINCT STATE into :&FT.COLS separated by ','
from &FT._DENOMINATORS;
      %let i=%eval(&I+1);  
      %let FT=%scan(%bquote(&SYSPBUFF),&I);
      %end;
%mend SUBST;
%SUBST(IP,LT,OT);
Quit;
%Put &&FT.COLS;

试试下面的公式。进行了一些更改:

  1. %subst() 宏移到 PROC SQL 之外,以便它可以先编译。

  2. do-while 循环转换为 do i = 1 to ndo-while 循环在最后一次迭代中产生了一个空白值 &FT

  3. 创建的所有宏都明确设为全局。

代码:

%macro SUBST() / parmbuff; 

    %do i = 1 %to %sysfunc(countw(%bquote(&syspbuff.) ) ); 
        %let ft = %scan(%bquote(&syspbuff.), &i.);
        %global &FT.COLS;

        Select DISTINCT STATE into :&FT.COLS separated by ','
        from &FT._DENOMINATORS;

    %end;
%mend SUBST;

Proc Sql noprint;
    %SUBST(IP,LT,OT);
Quit;

%put IP: &IPCOLS;
%put LT: &LTCOLS;
%put OT: &OTCOLS;

第一个问题是您没有尝试引用您创建的宏变量。宏变量将被命名为 IPCOLS、LTCOLS 和 OPCOLS。

主要问题是宏变量在宏结束后可能不存在,因为您在宏 运行 时创建了它们。

确保您正在创建的宏变量不是宏的局部变量。当您引用一个宏变量而 运行 一个宏时,它首先使用具有该名称的现有宏变量。如果 none 存在,那么它会在局部符号 table 中为宏创建一个新的。当宏完成时,局部符号 table 消失了。您可以使用 %symexist() 函数来检查宏变量是否已经存在。如果没有,您可以创建一个 GLOBAL 宏变量,该变量将在宏执行结束后继续存在。

首先不要在其他代码中间定义宏。先定义再使用。这样你的代码就更容易 read/edit/debug 了。根据您计划如何使用它,您甚至可能希望宏生成 PROC SQL 和 QUIT 语句。

此外,无需使用 PARMBUFF 选项来传递值列表。只是不要在值之间使用逗号。使用 space 或其他一些字符。 (请注意,您可能不希望在您正在创建的宏变量的值中使用逗号,但这取决于 STATE 是什么以及您打算如何使用这些宏变量。)

%macro subst(list);
%local i prefix mvar;
%do i=1 %to %sysfunc(countw(&list,%str( )));
  %let prefix=%scan(&list,&i,%str( ));
  %let mvar=&prefix.cols;
  %if not %symexist(&mvar) %then %global &mvar;
select DISTINCT STATE
  into :&mvar separated by ','
  from &prefix._DENOMINATORS
;
%end;
%mend subst;

proc sql noprint;
%SUBST(IP LT OT);
quit;
%put &=IPCOLS;
%put &=LTCOLS;
%put &=OTCOLS;