我想"自动化" PROC使用列表和循环在SAS中调用。例如,我想使用计算结果表列表调用PROC EXPORT,例如:
{{1}}
这应该创建一个" file.xls"并在"表"中为每个表插入一张表。我知道这应该以某种方式使用宏,但无法确定正确的语法。
答案 0 :(得分:2)
只是因为你的解决方案非常长...使用宏循环。请参阅SAS 9.4 Macro文档。附录有几个代码示例。
这是一个简单的宏循环,它使用COUNTW来确定术语数,并创建宏变量SHEET来保存列表的当前值。
%macro iterm(lst);
%let finish=%sysfunc(countw(&lst));
%do i = 1 %to &finish;
%let sheet= %scan(&lst,&i);
PROC EXPORT DATA= WORK.&sheet OUTFILE="file.xls" DBMS=EXCEL REPLACE;
SHEET=&sheet;
RUN;
%end;
%mend iterm;
%iterm(LSM Diff);
答案 1 :(得分:1)
您可以使用XLSX引擎和PROC COPY。
libname out xlsx 'file.xlsx';
proc copy inlib=work outlibe=out ;
select FitStatistics Type3_Tests LSM Diff ;
run;
libname out;
答案 2 :(得分:-2)
我自己找到了一个解决方案,虽然它没有单独使用纯SAS功能。如果有人提出了一个更简单的解决方案,我会投票并接受它作为最终答案。
有一篇由Jim Anderson撰写的SAS会议文章,他用自己的for loop macro解决了这个问题。 鉴于这个宏,我们可以做到
%for(tables, values=FitStatistics Type3_Tests LSM Diff, do= %nrstr(
PROC EXPORT DATA= WORK.&tables
OUTFILE="file.xls"
DBMS=EXCEL REPLACE;
SHEET=&tables;
RUN;
))
这正是我的想法。为了避免死链接问题,我引用了他的文章中给出的宏。它有效但对我来说很模糊。
%macro for(macro_var_list,data=,values=,array=,to=,from=1,by=1,do=,delim=%str(
),length=);
%global _for_loop_gen;
%if &_for_loop_gen=%str( ) %then %let _for_loop_gen=0;
%local _for_loop_itid _for_loop_ct _for_loop_code _for_loop_i
_for_loop_val1 _for_loop_var1 _n_ _for_loop_set
_for_loop_arrays _for_loop_values _for_loop_to
_for_loop_var_num;
%let _for_loop_set=%length(&data);
%let _for_loop_arrays=%length(&array);
%let _for_loop_values=%length(&values);
%let _for_loop_to=%length(&to);
%if (&_for_loop_set>0)+(&_for_loop_arrays>0)+
(&_for_loop_values>0)+(&_for_loop_to>0)>1 %then
%do;
%put ERROR: "for" macro only one of "data=", "to=", "values=" or "array=" allowed;
%return;
%end;
%let _for_loop_code=&do;
%if %eval(%index(&do,%nrstr(%if))+%index(&do,%nrstr(%do))) %then
%do; %* conditional macro code - need to embed in macro;
%let _for_loop_gen=%eval(&_for_loop_gen+1);
%unquote(%nrstr(%macro) _for_loop_&_for_loop_gen(); &do %nrstr(%mend;))
%let _for_loop_code=%nrstr(%_for_loop_)&_for_loop_gen();
%end;
%let _for_loop_ct=0;
%if &_for_loop_set %then
%do; %* loop over dataset;
%let _for_loop_itid=%sysfunc(open(&data));
%if &_for_loop_itid=0 %then
%do;
%put ERROR: cant open dataset data=&data;
%return;
%end;
%do %while(%sysfunc(fetch(&_for_loop_itid,NOSET))>=0);
%let _for_loop_ct=%eval(&_for_loop_ct+1);
%let _n_=&_for_loop_ct;
%let _for_loop_i=1;
%let _for_loop_var1=%scan(¯o_var_list,1,%str( ));
%do %while(%str(&_for_loop_var1) ne %str( ));
%let _for_loop_var_num=%sysfunc(varnum(&_for_loop_itid,&_for_loop_var1));
%if &_for_loop_var_num=0 %then
%do;
%put ERROR: "&_for_loop_var1" is not a dataset variable;
%return;
%end;
%if %sysfunc(vartype(&_for_loop_itid,&_for_loop_var_num))=C %then
%do; %* character variable;
%let _for_loop_val1=%qsysfunc(getvarc(&_for_loop_itid,&_for_loop_var_num));
%if %sysfunc(prxmatch("[^\w\s.]+",&_for_loop_val1)) %then
%let &_for_loop_var1=%qtrim(&_for_loop_val1);
%else
%let &_for_loop_var1=%trim(&_for_loop_val1);
%end;
%else
%do; %* numeric variable;
%let &_for_loop_var1=%sysfunc(getvarn(&_for_loop_itid,&_for_loop_var_num));
%end;
%let _for_loop_i=%eval(&_for_loop_i+1);
%let _for_loop_var1=%scan(¯o_var_list,&_for_loop_i,%str( ));
%end;
%unquote(&_for_loop_code)
%end;
%let _for_loop_i=%sysfunc(close(&_for_loop_itid));
%return;
%end;
%else %if &_for_loop_arrays %then
%do; %* loop over one or more arrays;
%local _for_loop_arrays _for_loop_array1 _for_loop_len;
%if ¯o_var_list=%str( ) %then %let macro_var_list=&array;
%let _for_loop_arrays=&array;
%let _for_loop_array1=%scan(&array,1,%str( ));
%if &length ne %str( ) %then
%let _for_loop_len=&length;
%else
%do; %* getnumber of iterations from first macro array;
%if %symexist(&_for_loop_array1.n) %then
%let _for_loop_len=&&&_for_loop_array1.n;
%else
%do;
%put ERROR: "for" macro for arrays needs "length=" argument;
%return;
%end;
%end;
%do _for_loop_ct=1 %to &_for_loop_len;
%let _n_=&_for_loop_ct;
%let _for_loop_i=1;
%let _for_loop_var1=%scan(¯o_var_list,1,%str( ));
%do %while(%str(&_for_loop_var1) ne %str( ));
%let _for_loop_array1=%scan(&_for_loop_arrays,&_for_loop_i,%str( ));
%if &_for_loop_array1=%str( ) %then
%do; %* more variables than arrays;
%put ERROR: "for" macro has more variables than arrays;
%return;
%end;
%let _for_loop_val1=%superq(&_for_loop_array1&_n_);
%if %sysfunc(prxmatch("[^\w\s.]+",&_for_loop_val1)) %then
%let &_for_loop_var1=%qtrim(&_for_loop_val1);
%else
%let &_for_loop_var1=%trim(&_for_loop_val1);
%let _for_loop_i=%eval(&_for_loop_i+1);
%let _for_loop_var1=%scan(¯o_var_list,&_for_loop_i,%str( ));
%end;
%unquote(&_for_loop_code)
%end;
%return;
%end;
%else %if &_for_loop_values ne 0 %then
%do; %* loop over list of values;
%local _for_value_index _for_loop_values _for_loop_delim _for_loop_extra;
%let _for_loop_values=&values;
%let _for_loop_delim=&delim;
%let _for_value_index=1;
%if ¯o_var_list=%str( ) %then
%do; %*empty variable list - perhaps (s)he just wants &_n_;
%let macro_var_list=_for_loop_extra;
%end;
%do %while(1);
%let _for_loop_ct=%eval(&_for_loop_ct+1);
%let _n_=&_for_loop_ct;
%let _for_loop_i=1;
%let _for_loop_var1=%scan(¯o_var_list,1,%str( ));
%do %while(%str(&_for_loop_var1) ne %str( ));
%let _for_loop_val1=%scan(&_for_loop_values,&_for_value_index,&_for_loop_delim);
%let _for_value_index=%eval(&_for_value_index+1);
%if %length(&_for_loop_val1)=0 %then
%do; %* end of values before end of variables, terminate iteration;
%return;
%end;
%let &_for_loop_var1=&_for_loop_val1;
%let _for_loop_i=%eval(&_for_loop_i+1);
%let _for_loop_var1=%scan(¯o_var_list,&_for_loop_i,%str( ));
%end;
%unquote(&_for_loop_code)
%end;
%end;
%else %if &_for_loop_to %then
%do; %* loop from &from to &to by &by;
%*local ¯o_var_list;
%let _for_loop_var1=%scan(¯o_var_list,1,%str( ));
%let _for_loop_ct=1;
%do _for_loop_i=&from %to %eval(&to) %by &by;
%let _n_=&_for_loop_ct;
%if %str(&_for_loop_var1) ne %str( ) %then %let &_for_loop_var1=&_for_loop_i;
%let _for_loop_ct=%eval(&_for_loop_ct+1);
%unquote(&_for_loop_code)
%end;
%return;
%end;
%put ERROR: for macro requires a "data", "values", "to" or "array" keyword;
%mend for;