我可以从宏变量创建宏名称吗
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;
试试下面的公式。进行了一些更改:
%subst()
宏移到 PROC SQL 之外,以便它可以先编译。
do-while
循环转换为 do i = 1 to n
。 do-while
循环在最后一次迭代中产生了一个空白值 &FT
。
创建的所有宏都明确设为全局。
代码:
%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: <COLS;
%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;
我想使用 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;
试试下面的公式。进行了一些更改:
%subst()
宏移到 PROC SQL 之外,以便它可以先编译。do-while
循环转换为do i = 1 to n
。do-while
循环在最后一次迭代中产生了一个空白值&FT
。创建的所有宏都明确设为全局。
代码:
%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: <COLS;
%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;