【问题标题】:Generate SAS code using input specifications使用输入规范生成 SAS 代码
【发布时间】:2019-12-09 06:55:28
【问题描述】:

我们有一组在 SAS 中开发的预定义宏,用于使用 SAS 数据集生成表格、列表和图形。我的要求是专门为表自动生成 SAS 代码。有一些固定数量的模板可用于要生成的表。此外,SAS 程序可用于生成每个表输出。每当需要从这些模板生成表时,都需要修改相关的 SAS 程序以生成所需的输出。

为了避免每次单独编写 SAS 程序以生成固定类型的输出的冗余,我想创建一个生成 SAS 代码的工具。此代码将用作生成表的源。

我准备了一个 Excel 工作簿,其中包含构建程序所需的所有详细信息(如各种参数及其值,例如标题、脚注、源数据集、按行/列分组)。在 Excel 中创建的简单用户表单用于显示和配置这些参数。

现在的问题是——如何使用 Excel VBA 生成 SAS 语句?以及如何使用 Excel VBA 与 SAS 连接以执行 SAS 程序?

如果您以前做过类似的事情,或者您对此类问题陈述有任何想法,请在此处分享。任何帮助都是非常可观的。

谢谢。

【问题讨论】:

  • 我建议尝试 SAS Institute excel 论坛。另一个建议是查看 VBA 中的 SAS 插件对象库。我管理的唯一 VBA 集成是更新 SAS 表 :-)
  • 我不确定你在这里问什么。您不确定如何从 VBA 生成文本文件?如果你知道怎么做,生成 SAS 代码应该不是问题。但是,我过去曾在这样的系统上工作过,我也会在 SAS 中生成 SAS 代码;这似乎是系统内更好的职责分离。编写一个 SAS 程序,读取 Excel 表,生成合适的 SAS 代码来创建表格,然后运行 ​​SAS 代码。
  • 感谢克里斯的评论。为了进一步澄清我的问题 - 我正在寻找通过 VBA 生成 SAS 代码的解决方案。我有兴趣看看是否有人已经以更合乎逻辑的方式完成了这类事情。到目前为止,我所做的方式非常简单,通过编写自己的逻辑规则来生成预期的代码。

标签: excel vba automation sas


【解决方案1】:

我不会涉及 VBA。我会编写一个 SAS 程序来读取需求,生成表格并将它们推回一个新的 Excel 程序。如果您想完全从 Excel 程序中驱动它,我建议您使用 SAS Add-In for Excel 而不是 VBA 代码,尽管您可以通过 VBA 触发它。 Chris Hemidinger 是这类问题的 SAS 专家,他确实在 community.sas.com 上发帖,因为另一位用户表示您应该在那里发帖(在 cmets 中)。

创建空表是一个简单的过程,但报告表通常具有非常具体的布局,因此您可以进一步概括此过程。例如,我有一个为数据集创建标准表 1(特征表)的宏,我只需要按类型(连续、分类、二进制)指定输入变量,然后生成输出并可以推送通过 ODS EXCEL 表现出色。我还使用 PROC REPORT 来格式化它,因为我会为不同的变量交替地对行进行着色,这样更容易阅读/显示。

/*
This macro creates a table of charateristics for the variables listed.  
It handles categorical, binary and continuous variables and produces and output dataset that can be further customized. No statistical information is
included in this analysis
*/

/*Parameters to be set:
dsetin - name of dataset to be analyzed
cont = macro variable list of variable names, ie cont=age weight height
cat=list of categorical variables ie cat=sex grade
bin=binary variables, such as smoking now, smoking ever
dsetout=name of output dataset
Run example at the end for a sample output dataset call sample_table_char in the work directory
*/


*options mprint symbolgen;
%macro table_char(dsetin, cont, cat, bin, dsetout);


*delete old dataset;

proc datasets nodetails nolist;
    delete &dsetout;
quit;

/****************************************************************
Handle Categorical Variables
****************************************************************/

*loop through variable list;
%let i=1;
%do %while (%scan(&cat, &i, " ") ^=%str());
%let var=%scan(&cat, &i, " ");  

*Get format for variable;
data _null_;
 set &dsetin;
 call symput("var_fmt", vformat(&var));
run;



proc freq data=&dsetin noprint;
    table &var/missing out=tab_var;
run;



data temp1;
    length categorical $200.; format categorical $200.;
    length value $200.; format value $200.;

    set tab_var;
    percent=percent/100;
    categorical=put(&var., &var_fmt.);
    if _n_=1 then do;
        value=put(count, 8.)||"("||compress(put(percent, percent8.1))||")";
        order=2;
        output;
        order=1;
        value='';
        categorical=propcase(vlabel(&var.));
        output;
    end;
    else do;
        order=2;
        value=put(count, 8.)||"("||compress(put(percent, percent8.1))||")";
        output;

    end;

    keep categorical value order;
run;

proc sort data=temp1 out=temp2 (drop=order); by order categorical; run;


proc append base=&dsetout data=temp2;
run;

*clean up;

proc datasets nodetails nolist;
    delete tab_var temp1 temp2;
run; quit;

*Increment counter;
%let i=%eval(&i+1);
%end; *Categorical;

/****************************************************************
Handle Continuous Variables
****************************************************************/

%let i=1;
%do %while (%scan(&cont, &i, " ") ^=%str());
%let var=%scan(&cont, &i, " "); 



proc means data=&dsetin (rename=&var=vn) noprint;
var vn;
output out=table_var n= nmiss= mean= min= max= std= median= p25= p75= p90=/autoname;
run;

*get label of variable for clean reporting;
data _null_;
 set &dsetin;
 call symput("var_label", vlabel(&var));
run;




data temp1;
    length categorical $200.; format categorical $200.;
    format value $200.; length value $200.;

    set table_var;

    categorical="&var_label.";
    value=.;
    output;

    categorical='Count(Missing)';
    value=put(vn_n, 5.)||"("||compress(put(vn_nmiss, 5.))||")";
    output;

    categorical='Mean (SD)';
    value=put(vn_mean, 8.1)||"("||compress(put(vn_stddev, 8.1))||")";
    output;

    categorical='Median (IQR)';
    value=put(vn_median, 8.1)||"("||compress(put(vn_p25, 8.1))||" - "||compress(put(vn_p75, 8.1))||")";
    output;

    categorical='Range';
    value=put(vn_min, 8.1)||" - "||compress(put(vn_max, 8.1));
    output;

    categorical='90th Percentile';
    value=put(vn_p90, 8.1);
    output;



    keep categorical value;
run;


proc append base=&dsetout data=temp1;
run;

*clean up;

proc datasets nodetails nolist;
    delete table_var temp1;
run; quit;

*Increment counter;
%let i=%eval(&i+1);
%end; *Continuous;

/*****************************************************************
Handle Binary Variables (only report 1s)
*****************************************************************/

%let i=1;
%do %while (%scan(&bin, &i, " ") ^=%str());
%let var=%scan(&bin, &i, " ");  



proc freq data=&dsetin noprint;
    table &var/missing out=tab_var;
run;

data tab_var;
    set tab_var;
    where &var=1;
run;

data temp1;
    length categorical $200.; format categorical $200.;
    length value $200.; format value $200.;

    set tab_var;
    percent=percent/100;
    if _n_=1 then do;
        value=put(count, 8.)||"("||compress(put(percent, percent8.1))||")";
        order=1;
        categorical=propcase(vlabel(&var.));
        output;
    end;
    keep categorical value;
run;




proc append base=&dsetout data=temp1;
run;

*clean up;

proc datasets nodetails nolist;
    delete tab_var temp1;
run; quit;

*Increment counter;
%let i=%eval(&i+1);
%end;*Binary;


%mend table_char;


/* *Example of macro usage; */
/* data sample; */
/*  set sashelp.class; */
/*  female=ifn( sex='F',1,0); */
/* run; */
/*  */
/*  */
/* %table_char(sample, height weight age, sex, female, sample_table_char); */

【讨论】:

  • 感谢 Reeza 提供寻找可能解决方案的指针。
猜你喜欢
  • 2018-02-21
  • 2018-03-02
  • 2018-03-28
  • 2021-05-16
  • 2020-08-24
  • 2010-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多