Sas 根据观测数量控制输出(ODS或PROC)

Sas 根据观测数量控制输出(ODS或PROC),sas,Sas,我目前有一个SAS进程,它可以生成多个数据集,无论它们是否有观测值。如果nobs>0,我想确定一种基于观察总数控制导出过程的方法,然后导出。我的第一次尝试是使用if/then逻辑将select与数据集中的宏var计数obs进行比较- DATA _NULL_; SET A_EXISTS_ON_B; IF &A_E > 0 THEN DO; FILE "C:\Users\ME\Desktop\WORKLIST_T &PDAY..xls"; P

我目前有一个SAS进程,它可以生成多个数据集,无论它们是否有观测值。如果nobs>0,我想确定一种基于观察总数控制导出过程的方法,然后导出。我的第一次尝试是使用if/then逻辑将select与数据集中的宏var计数obs进行比较-

DATA _NULL_;
   SET A_EXISTS_ON_B;
   IF &A_E > 0 THEN DO;
      FILE "C:\Users\ME\Desktop\WORKLIST_T &PDAY..xls";
      PUT TASK;
   END;
RUN;
这里的问题是,我没有办法用多张图纸将多个集合写入同一工作簿,或者我有办法吗


此外,每当我尝试添加另一个具有类似逻辑的Do块时,执行都会失败。如果不能用空数据来实现这一点,ODS就是答案吗?

建议您搜索不同的方法来编写XLS文件

关于使用数据步骤或过程步骤,数据步骤可以容忍具有0 OB的数据集。如果SET语句读取的数据集具有0 OB,它将简单地结束该步骤。所以你不需要特殊的逻辑。大多数进程还容纳0 obs数据集,而不会引发警告或错误

例如:

1218  *Make a 0 obs dataset;
1219  data empty;
1220    x=1;
1221    stop;
1222  run;

NOTE: The data set WORK.EMPTY has 0 observations and 1 variables.

1223
1224  data want;
1225    put "I run before SET statement.";
1226    set empty;
1227    put "I do not run after SET statement.";
1228  run;

I run before SET statement.
NOTE: There were 0 observations read from the data set WORK.EMPTY.
NOTE: The data set WORK.WANT has 0 observations and 1 variables.

1229
1230  proc print data=empty;
1231  run;

NOTE: No observations in data set WORK.EMPTY.
但请注意,正如Joe指出的,PROC EXPORT将很高兴地导出一个包含0个obs的数据集,并编写一个包含0个记录的文件,如果该文件已经存在,则会覆盖它。e、 g:

1582  proc export data=sashelp.class outfile="d:\junk\class.xls";
1583  run;

NOTE: File "d:\junk\class.xls" will be created if the export process succeeds.
NOTE: "CLASS" range/sheet was successfully created.

1584
1585  data class;
1586    stop;
1587    set sashelp.class;
1588  run;

NOTE: The data set WORK.CLASS has 0 observations and 5 variables.

1589
1590  *This will replace class.xls";
1591  proc export data=class outfile="d:\junk\class.xls" replace;
1592  run;

NOTE: "CLASS" range/sheet was successfully created.
ODS语句可能也会这样做

我使用宏检查数据集是否为空。所以答案是:

您想要做的核心工作,即有条件地执行代码,可以通过多种方式之一来完成

假设我们有一个将数据集导出到excel的短宏。非常简单

%macro export_to_excel(data=,file=,sheet=);
 proc export data=&data. outfile=&file. dbms=excel replace;
  sheet=&sheet.;
 run;
%mend export_to_excel;
现在让我们假设我们想有条件地这样做。我们如何做在某种程度上取决于我们现在在代码中如何调用这个宏

假设你有:

%let wherecondition=1; *always true!;

data class;
  set sashelp.class;
  if &wherecondition. then output;
run;

%export_to_excel(data=class,file="c:\temp\class.xlsx", sheet=class1);
现在,您希望使其仅在类中有一些行时导出,对吗。因此,您可以在课堂上获得obs:

proc sql;
  select count(1) into :classobs from class;
quit;
现在你需要以某种方式将其合并。在这种情况下,最简单的方法是向导出宏添加条件。开放代码不允许有条件地执行代码,所以它需要在宏中

因此,我们:

%macro export_to_excel(data=,file=,sheet=,condition=1);
 %if &condition. %then %do;
  proc export data=&data. outfile=&file. dbms=excel replace;
   sheet=&sheet.;
  run;
 %end;
%mend export_to_excel;
然后将计数添加到通话中:

%export_to_excel(data=class,file="c:\temp\class.xlsx", sheet=class1,condition=&classobs.)
Tada,现在它不会在0时尝试导出。太好了

如果此代码已在宏中,则不必更改导出宏本身。您可以简单地将%if%放在宏调用周围。但这只是在整个事情已经是一个宏的情况下-%if不允许在宏之外抱歉

现在,如果您要导出一大堆数据集,并且要从某个数据集生成导出调用,那么您可以在那里添加条件,比这更容易、更顺利

基本上,如果有意义,可以手工制作,或者使用proc sql或proc contents或您选择的其他方法制作一个数据集,每个数据集包含一行要导出的数据,其中包含四个变量:数据集名称、要导出的文件、要导出的工作表,除非与数据集名称相同,以及该数据集的观察计数。通常,前三个表是手工制作的,然后通过sql或其他方式合并/更新到每个数据集的OB数

然后您可以生成要导出的调用,如下所示:

proc sql;
 select cats('%export_to_excel(data=',dataname,',file=',filename,',sheet=',sheetname,')')
  into :explist separated by ' '
  from datasetwithnames
  where obsnum>0;
quit;

&explist.;  *this actually executes them;

假设obsnum是使用obs的创建的新变量,其他变量显然已命名。这不会拉一条包含0个观察值的线-因此它从不尝试执行导出。这适用于初始导出宏,也适用于修改后的宏。

更大的问题是,您不能像这样直接写入XLS…似乎可以创建实际的excel文件…注意:有3条记录写入了文件C:\Users\Silvery\Desktop\WORKLIST\U t 2015-08-25.XLS。最小记录长度为1。最大记录长度为1。注意:从数据集WORK.FD_EXISTS__ON_PA读取了3个观察值。注意:使用的数据语句总处理时间:实时0.03秒cpu时间0.03秒。当然,它不会创建实际的excel文件。它可能会创建excel愿意作为excel文件处理的内容,但它不是excel文件。SAS数据步骤只能创建基于文本的文件,如平面文件、逗号分隔文件等。XLS是一种二进制格式,直到很晚才开始成为openXML,但仍然不是原始文本。但是如果您尝试导出一个0 obs数据集呢?它会覆盖某些内容,不是吗?是的,我想PROC导出与OP可能需要的适应方式不同:我会补充答案。这就是我需要的!我有一个正确的概念,直到选择进入:部分,以确定观察的数量…只是不知道如何把它放在一起!!谢谢你的回答,更重要的是回答背后的解释…和你平时一样非常有帮助+1.