如何在SAS中循环过程?

时间:2016-12-18 08:25:13

标签: sas

我想"自动化" PROC使用列表和循环在SAS中调用。例如,我想使用计算结果表列表调用PROC EXPORT,例如:

{{1}}

这应该创建一个" file.xls"并在"表"中为每个表插入一张表。我知道这应该以某种方式使用宏,但无法确定正确的语法。

3 个答案:

答案 0 :(得分:2)

只是因为你的解决方案非常长...使用宏循环。请参阅SAS 9.4 Macro文档。附录有几个代码示例。

这是一个简单的宏循环,它使用COUNTW来确定术语数,并创建宏变量SHEET来保存列表的当前值。

http://support.sas.com/documentation/cdl/en/mcrolref/69726/HTML/default/viewer.htm#n1qvxz5u3uru7yn1nk7q64ohvwak.htm

 %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(&macro_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(&macro_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 &macro_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(&macro_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(&macro_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 &macro_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(&macro_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(&macro_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 &macro_var_list; 
    %let _for_loop_var1=%scan(&macro_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;