SAS编程:如何将数据集批量输出到Excel中?

欢迎关注:SAS茶谈!

最近,为了解一个项目的数据结构,需要查看不少RawData。简单的记录筛选,SAS操作起来不复杂,但是对于大批量数据集记录查看,SAS筛选就略显繁琐。这种情况下,将数据集批量输出到EXCEL中进行查看,是一个不错的方法。

数据集批量输出的要达到什么样的效果呢?我想的是,所有数据集都在一个EXCEL文件中,数据集名称作为对应的Sheet名称,每个表单冻结首行,并且直接设置好首行筛选。这样打开输出的EXCEL文件,就可以不需要多余的设置,直接浏览、筛选数据。

在SAS编程中,常见的批量处理的方法有两种,一是宏程序中的宏循环,二是call execute语句

下面介绍整个输出的实现过程,先从单个数据集输出开始。

1. 单个数据集的输出

SAS程序参考之前的文章SAS编程:输出SAS数据集(Listing)到EXCEL,Excel文件的sheet名称设置、冻结首行、自动筛选都在选项中进行指定。

ods excel file = "E:\999_test.xlsx" 
     options(sheet_name="Class"  frozen_headers="Yes" autofilter = "Yes");

proc report data = sashelp.class;
 column _all_;
run;

ods excel close;

输出结果如下:

单个数据集实现了对应格式的输出。

2. 两个数据集的输出

还是参考之前的参考之前的文章SAS编程:输出SAS数据集(Listing)到EXCEL,第二个ods excel语句输出不添加file=语句,这样两个数据集就输出到同一个EXCEL文件的不同sheet中。

ods excel file = "E:\999_test\test.xlsx" 
     options(sheet_name="Class"  frozen_headers="Yes" autofilter = "Yes");

proc report data = sashelp.class;
run;

ods excel 
     options(sheet_name="Cars" frozen_headers = "Yes" autofilter="Yes");

proc report data = sashelp.cars;
 column _all_;
run;

ods excel close;

3个及以上数据集的输出,与此类似。

3. 逻辑库内所有数据集的输出

显然,如果照着上面举例手动添加数据集的输出程序,输出逻辑库中的所有数据集的过程就太过繁琐,所以需要批量处理。

常见的批量处理的方法有两种,一是宏程序,二是call execute语句。下面来介绍这两种方法的实现。

不管哪种方法,首先需要获取逻辑库中的数据集名称,以方便引用。这里,以SASHelp逻辑库中前10个数据集进行举例。

data tables;
  set sashelp.vtable;
  where libname = "SASHELP";

  if _n_ <= 10;
  keep libname memname;
run;

输出结果如下:

Tables
3.1 宏程序批量输出数据集

SAS宏可以理解成是“代码生成器”,宏程序的批量处理是通过宏循环实现

参考两个数据集输出的代码,对于不同数据集,sheet_name=data=选项值是变化的。考虑到SAS数据集名称是不区分大小写,这两个选项值可以看作是一致的。

宏循环的思路是,将数据集的名称保存到各个宏变量中,这些宏变量名称的前缀相同,后缀以序号结尾。这里我将其称为,宏变量序列。获取宏变量序列后,利用循环变量,从而实现“代码生成”的效果。

3.1.1 宏变量序列的生成

宏变量序列的生成常用也有2种方法:

  1. Proc SQL 中的into :语句
  2. Data步中的call symputx语句
3.1.1.1 Proc SQL生成宏变量序列

into :语句之前介绍过,可以参考SAS编程:Proc SQL生成宏变量时INTO子句的使用 。使用这个方法,需要获取数据集的记录数,这里就不介绍如何获取数据集的记录数了,直接手动赋值为10。

proc sql noprint;
 select memname
   into :memname1- :memname10
   from tables;
quit;

%put memname1 = &memname1.;
%put memname10 = &memname10.;

输出结果如下:

3.1.1.2 Data 步中生成宏变量序列

与SQL中依靠后缀序列进行计数不同,Data步中数据集自带的自动变量_n_可以实现计数的功能。

data _null_;
   set tables;
    call symputx("name"||strip(put(_n_, best.)), strip(memname));
run;

%put memname1 = &name1.;
%put memname10 = &name10.;

输出结果与SQL结果一致,可以看出Data步方法实现可以省去获取数据集记录数的步骤,整体上代码比较简洁

3.1.2 宏循环批量输出数据集

宏循环需要处理,第一个数据集与其他数据集输出的不同(后续数据集不需要file=选项),用判断语句进行区分。

如果想要查看宏程序具体的运行代码,可以参考文章SAS编程:检查宏程序issue思路介绍,里面有对mprint选项的介绍。

调试程序的时候,发现SASHelp.BIRTHWGT这个数据集居然有10万条记录,ods excel语句输出会出现内存不足等问题,于是使用ods tagsets.excelxp进行输出

%macro loop;
 
%do a = 1 %to 10;
  %if &a. = 1 %then %do;
    ods tagsets.excelxp file = "E:\999_test\test.xlsx" 
      options(sheet_name="&name1."  frozen_headers="Yes" autofilter = "Yes");

    proc report data = sashelp.&name1.;
     column _all_;
    run;
  %end;
  
  %else %do;
    ods tagsets.excelxp options(sheet_name="&&name&a." frozen_headers = "Yes" autofilter="Yes");

    proc report data = sashelp.&&name&a.;
     column _all_;
    run;
  %end;

%end;

ods tagsets.excelxp close;

%mend;

%loop;

但使用ods tagsets.excelxp有会出现其他一些问题,这一点后续另写文章介绍处理。以上输出文件用EXCEL打开的话,会显示如下内容:

WPS可以正常打开输出文件,10个数据集完整的输出到EXCEL文件中。

3.2 call execute()批量输出数据集
3.2.1 call execute()的简单介绍

官方文档是这样,介绍call execute()语句的:

Resolves the argument, and issues the resolved valuefor execution at the next step boundary.
(解析参数,并发出已解析的值以便在下一步边界执行。)

call execute()是为了在Data步中执行其他完整的SAS代码,括号里面的内容是一段完整的字符串,举个简单的例子。

data _null_;
  call execute(
  '
  data class;
    set sashelp.class;
  run;
  '
 );
run;

以上的代码就是直接引号中的程序。这里读者可能会有疑问,直接写一遍引号中的代码再运行,不是更方便吗?

单从直接调用简单的SAS程序来讲,这确实是多此一举。但是,call execute()是可以直接调用数据集中的记录值,进行运行的。再举个例子:

data tmp;
   a = "class";
run;

data _null_;
  set tmp;
  call execute(
  '
  data class;
    set sashelp.'||strip(a)||';
  run;
  '
 );
run;

以上程序运行的结果,是解析数据集Tmp中变量a的值,带入引号中的程序。可以这样理解,括号中的内容依旧是一个待运行的字符串,只不过这个字符串拼接了Tmp数据集中变量a的值

读者看到这里可能又会有疑问,如果数据集中有多条数据,call execute()将如何处理呢?

如果数据集中有多条数据,call execute()就会运行多次程序,按数据集记录的行数进行迭代,每一次运行的程序会更新"变量a"的值

如果Tmp数据集中有2条记录,class, cars,那么最后执行的代码如下:

 data class;
    set sashelp.class;
 run;

 data class;
    set sashelp.cars;
 run;
3.2.2 call execute()批量输出数据集到EXCEL中

有了上面的介绍,直接看批量输出数据集的代码:

data _null_;
  set tables end = eof;
  if _n_ = 1 then call execute(
  '
  ods tagsets.excelxp file = "E:\999_test\test.xlsx" 
    options(sheet_name="'||strip(memname)||'"  frozen_headers="Yes" autofilter = "Yes");

  proc report data = sashelp.'||strip(memname)||';
    column _all_;
  run;
  '
  );

  else call execute(
  '
  ods tagsets.excelxp 
    options(sheet_name="'||strip(memname)||'"  frozen_headers="Yes" autofilter = "Yes");

  proc report data = sashelp.'||strip(memname)||';
    column _all_;
  run;
  '
  );

  if eof then call execute(
  '
  ods tagsets.excelxp close;
  '
  );
run;

程序中,通过_n_这个自动变量进行区分是否是第一条记录,然后进行对应的设置;end = eof选项,新建eof变量用于判断记录是否到达尾行,尾行需要将输出进行关闭。

输出结果与前面SQL一致:

总结

文章介绍了2种将数据集批量输出到Excel中的方法,宏程序和call execute()语句。宏程序,是先将所有数据集名称保存到宏变量序列中,然后通过宏循环进行调用。call execute()语句,是通过数据集构建完整的运行程序。

本质上,宏循环和call execute()语句作用是相同的,都是“代码生成器”。

在介绍宏程序实现的过程中,还介绍了2种生成宏变量的序列的方法。

感谢阅读, 欢迎关注:SAS茶谈!
若有疑问,欢迎评论交流!

你可能感兴趣的:(SAS编程:如何将数据集批量输出到Excel中?)