data sample;
input x $;
datalines;
one
two
three
;
%macro variable_to_macvar(variable=, dataset=);
proc sql noprint;
select &variable into : outlist separated by ' '
from &dataset;
quit;
&outlist
%mend variable_to_macvar;
%put %variable_to_macvar(variable=x, dataset=sample);
预期输出:one two three
。 相反,我收到了错误。为什么?这可以解决吗?
我已经成功创建了一个非常相似的形式的其他宏,其中函数"返回"使用宏末尾的& macro变量而不使用分号的值。例如,这是一种类似的功能:
%macro zcat(first=5, last=15, prefix=freq);
%let x=;
%do i = &first %to &last;
%let x=&x &prefix.&i;
%end;
&x
%mend zcat;
%put %zcat();
答案 0 :(得分:3)
您不能以您尝试在此处执行的方式执行涉及运行proc或数据步骤的宏。您需要使用类似%sysfunc(dosubl(proc sql...))
的内容才能使其正常工作(假设您有SAS 9.3+ - 请参阅上面的Joe的回答)。否则,您不能在函数式宏中使用proc sql。
有关dosubl的更多详细信息: http://support.sas.com/documentation/cdl/en/lefunctionsref/67398/HTML/default/viewer.htm#p09dcftd1xxg1kn1brnjyc0q93yk.htm
这有点繁琐,但如果您真的想在早期版本的SAS中将其作为函数式宏工作,则可以使用open
,fetchobs
和{getvarc
来构造它。 {1}}而是功能。
更新:这是一个示例(使用call set
而不是getvarc
,因为事实证明这更简单),以防任何人需要在SAS 9.2或更早版本中执行此操作。
%macro variable_to_macvar(var,ds);
%local rc dsid i;
%let &var =;
%global outlist;
%let outlist=;
%let dsid = %sysfunc(open(&ds,i));
%syscall set(dsid);
%let rc = 0;
%let i = 0;
%do %while(&rc = 0);
%let i = %eval(&i + 1);
%let rc = %sysfunc(fetchobs(&dsid,&i));
%if &rc = 0 %then %let outlist = &outlist &&&var;
%end;
%let rc = %sysfunc(close(&dsid));
&outlist
%mend;
%put %variable_to_macvar(var=x, ds=sample);
现在适用于视图和普通数据集。
答案 1 :(得分:2)
DOSUBL在9.3中是可用的(但是实验性的)(至少,9.3TS1M2,我有)。这就是你如何做到的。
data sample;
input x $;
datalines;
one
two
three
;
%macro variable_to_macvar(variable=, dataset=);
%let rc=%sysfunc(dosubl(%str(
proc sql noprint;
select &variable into : outlist separated by ' '
from &dataset;
quit;
)));
&outlist
%mend variable_to_macvar;
%put %variable_to_macvar(variable=x, dataset=sample);;
如果您不能使用DOSUBL,或者想要避免使用实验性内容,则可以使用PROC FCMP而不是宏来执行此操作。如果您想编写函数,PROC FCMP可能适合您:实际上能够编写函数,而不必处理宏语言的烦恼。
答案 2 :(得分:1)
最后改变你的代码
%global outlist;
%variable_to_macvar(variable=x, dataset=sample);
%put &outlist;
%put想要只解析一个宏变量或一个值。它无法调用程序。所以调用你的宏,然后打印结果。
此外,从宏定义中删除&outlist
。对不起,我最初错过了。
编辑:替代。
将宏定义更改为
%macro variable_to_macvar(variable=, dataset=);
proc sql noprint;
select &variable into : outlist separated by ' '
from &dataset;
quit;
%put &outlist
%mend variable_to_macvar;
只需将%放入宏内。
%variable_to_macvar(variable=x, dataset=sample);
会将字符串打印到日志中。
答案 3 :(得分:0)
我们有一个实用程序宏,它可能是我们最常用的代码之一。它类似于@ user667489提供的代码,但包含一些不错的功能,包括错误捕获,允许字符和数字变量,允许您指定分隔符,引号,引号字符,数据集的过滤器等等。
我们只是将这个宏放在我们的自动调用库中,以便它可以用于我们所有的程序。运行宏的一些示例:
示例1 - 默认行为:
%put %variable_to_macvar(var=x, ds=samplex);
结果1:
one,two,three
不完全是所需的输出,因为默认的分隔符是逗号,虽然可以轻松更改...
示例2 - 指定使用空格字符作为分隔符:
%put %ds2list(iDs=samplex, iField=x, iDelimiter=%str( ));
结果2:
one two three
示例3 - 引用&示例用法
data names;
input name $;
datalines;
John
Jim
Frankie
;
run;
%put %ds2list(iDs=names, iField=name, iQuote=1);
proc sql noprint;
create table xx as
select *
from sashelp.class
where name in (%ds2list(iDs=names, iField=name, iQuote=1))
;
quit;
结果3:
以下内容将打印到日志中:
'John','Jim','Frankie'
注意我们不需要将结果保存到宏变量中以在SQL语句中使用它! Swweeet!这适用于SQL直通查询以及您可以将其抛出的任何其他数据步骤或proc语句。在上面的示例中,单行返回为' John'是找到的唯一一场比赛......
无论如何,这就是我们的解决方案......使用它的时间大约为10年,对我来说效果很好。这是宏:
/***************************************************************************
** PROGRAM: MACRO.DS2LIST.SAS
**
** UTILITY PROGRAM THAT DETECTS RETURNS A LIST OF FIELD VALUES FROM A
** DATASET IN DELIMITED FORMAT.
**
** PARAMETERS:
** iDs : THE LIBNAME.DATASET NAME THAT YOU WANT TO CHECK.
** iField : THE FIELD THAT CONTAINS THE VALUES YOU WANT RETURNED IN A
** DELIMITED FORMAT.
** iDelimiter: DEFAULT IS A COMMA. THE DELIMITER TO USE FOR THE RETURNED LIST.
** iDsOptions: ANY STANDARD DATASET OPTIONS THAT YOU WOULD LIKE TO APPLY SUCH
** AS A WHERE STATEMENT.
** iQuote : (0=NO,1=YES). DEFAULT=0/NO. DETERMINES WHETHER THE RETURNED
** LIST IS QUOTED OR NOT.
** iQuoteChar: (SINGLE,DOUBLE) DEFAULT=SINGLE. SPECIFIES WHETHER SINGLE
** OR DOUBLE QUOTES ARE USED WHEN QUOTING THE RETURNED LIST
**
*****************************************************************************
** VERSION:
** 1.8 MODIFIED: 11-OCT-2010 BY: KN
** ALLOW BLANK CHARACTER VALUES AND ALSO REMOVED TRAILING
** ALLOW PARENTHESES IN CHARACTER VALUES
*****************************************************************************/
%macro ds2list(iDs=, iField=, iDsOptions=, iDelimiter=%str(,), iQuote=0, iQuoteChar=single);
%local dsid pos rc result cnt quotechar;
%let result=;
%let cnt=0;
%if &iQuote %then %do;
%if "%upcase(&iQuoteChar)" eq "DOUBLE" %then %do;
%let quotechar = %nrstr(%");
%end;
%else %if "%upcase(&iQuoteChar)" eq "SINGLE" %then %do;
%let quotechar = %nrstr(%');
%end;
%else %do;
%let quotechar = %nrstr(%");
%put WARNING: MACRO.DS2LIST.SAS: PARAMETER IQUOTECHAR INCORRECT. DEFAULTED TO DOUBLE;
%end;
%end;
%else %do;
%let quotechar = ;
%end;
/*
** ENSURE ALL THE REQUIRED PARAMETERS WERE PASSED IN.
*/
%if "&iDs" ne "" and "&iField" ne "" %then %do;
%let dsid=%sysfunc(open(&iDs(&iDsOptions),i));
%if &dsid %then %do;
%let pos=%sysfunc(varnum(&dsid,&iField));
%if &pos %then %do;
%let rc=%sysfunc(fetch(&dsid));
%do %while (&rc eq 0);
%if "%sysfunc(vartype(&dsid,&pos))" = "C" %then %do;
%let value = %qsysfunc(getvarc(&dsid,&pos));
%if "%trim(&value)" ne "" %then %do;
%let value = %qsysfunc(cats(%nrstr(&value)));
%end;
%end;
%else %do;
%let value = %sysfunc(getvarn(&dsid,&pos));
%end;
/* WHITESPACE/CARRIAGE RETURNS REMOVED IN THE BELOW LINE */
/* TO ENSURE NO WHITESPACE IS RETURNED IN THE OUTPUT. */
%if &cnt ne 0 %then %do;%unquote(&iDelimiter)%end;%unquote("echar&value"echar.)
%let cnt = %eval(&cnt + 1);
%let rc = %sysfunc(fetch(&dsid));
%end;
%if &rc ne -1 %then %do;
%put WARNING: MACRO.DS2LIST.SAS: %sysfunc(sysmsg());
%end;
%end;
%else %do;
%put ERROR: MACRO.DS2LIST.SAS: FIELD &iField NOT FOUND IN DATASET %upcase(&iDs).;
%end;
%end;
%else %do;
%put ERROR: MACRO.DS2LIST.SAS: DATASET %upcase(&iDs) COULD NOT BE OPENED.;
%end;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put ERROR: MACRO.DS2LIST.SAS: YOU MUST SPECIFY BOTH THE IDS AND IFIELD PARAMETERS TO CALL THIS MACRO.;
%end;
%mend;