自动为宏

时间:2018-03-19 10:54:43

标签: sas documentation

我想为pdf个宏的集合构建文档html(或SAS)。是否有我可以遵循的标准(或推荐)工作流程?

我正在考虑导出我的所有宏并使用RRegex提取标题,说明,示例,变量描述和代码,然后使用markdown构建一个很好的奠定pdf每当我添加宏或更改说明或示例时,我都可以通过几个步骤进行更新(我希望不惜一切代价避免复制/粘贴)。

虽然它很乏味且不灵活,但我可能会重新发明轮子。

我的宏看起来都像这样:

*--------------------------------------------------------;
* ASSERT_EXIST                                           ;
* Fails explicitely when a table doesn't exist           ;
* Accepts a list of tables as input                      ;
*--------------------------------------------------------;
/* EXAMPLES
%assert_exist(not_a_table);   * prints explicit error and aborts;
%assert_exist(sashelp.class); * does nothing;
%assert_exist(sashelp.cars not_a_table sashelp.class); * prints explicit error and aborts;
*/
%macro assert_exist
(data /* table or list of tables */
);
%local i table;
%do i=1 %to %sysfunc(countw(&data,%str( )));
  %let table = %scan(&data,&i,%str( ));
  %if not %sysfunc(exist(&table)) %then %do;
    %put ERROR: Table &table doesnt exist!;
    %abort;
  %end;
%end;
%mend;

*----------------------------------------------;
* DROP                                         ;
* Delete table or list of tables               ;
* Default deletes all tables starting with _   ;
*----------------------------------------------;
/* EXAMPLES
data _x;
input char1 $ num1;
datalines;
a 1
b 2
;
%put %sysfunc(exist(_x)); * 1;
%drop(_x);
%put %sysfunc(exist(_x)); * 0;
*/
%macro drop
(data /* Name of table to drop, end name of table with ':' to delete all tables with this prefix */
);
%if &data= %then %let data = _:;
proc datasets nolist;
    delete &data;
run;
%mend;

*--------------------------------------------------------;
* HEAD                                                   ;
* select top rows                                        ;
*--------------------------------------------------------;
/* EXAMPLES
%head(sashelp.class,2) * keep only 2 first rows;
* %drop(_TEMP_); * clean up;
*/
%macro head
(data  /* source table */
,n     /* number of rows to keep */
,out   /* output table */
);
/* default values, checks, initialisations */
%if &data= %then %let data = _TEMP_;
%if &out=  %then %let out  = _TEMP_;
%if &out=. %then %let out  = &data;
%assert_exist(&data)
proc sql inobs=&n;
  CREATE TABLE &out AS
  SELECT *
  FROM &data;
quit;
%mend;

我的宏集正在增长我希望尽可能地尊重良好做法,但我在SAS中找不到与良好文档相关的更多信息。

@ Allan-Bowe给出了一个很好的答案,这可能是最好的做法,但遗憾的是我无法从我的工作计算机上安装doxygen,因此我正在寻找其他不需要外部软件的解决方案

2 个答案:

答案 0 :(得分:1)

无需重新发明轮子 - 文档的一个很好的方法是doxygen

我们将它用于开源Boemska MacroCore library(其中还列出了SAS宏开发的许多优秀实践)。

只需在标题中定义您的属性(接受降价),例如:

/**
  @file
  @brief Logs a key value pair a control dataset
  @details If the dataset does not exist, it is created.  Usage:

    %mp_setkeyvalue(someindex,22,type=N)
    %mp_setkeyvalue(somenewindex,somevalue)

  @param key Provide a key on which to perform the lookup
  @param value Provide a value
  @param type= either C or N will populate valc and valn respectively.  C is
               default.
  @param libds= define the target table to hold the parameters
  @version 9.2
  @author Allan Bowe
  @source https://github.com/Boemska/macrocore
  @copyright GNU GENERAL PUBLIC LICENSE v3
**/

然后简单地将doxygen指向源文件夹,告诉它使用哪个配置文件(SAS的一个好文件是here)然后选择文档的输出目录。

它看起来像this(我们即将进行文档更新,因此会在今天晚些时候发布修订后的链接)。

没有pdf选项,但它可以创建DOCBOOK格式的文件,可用于生成pdf:http://www.doxygen.nl/manual/config.html#config_docbook

答案 1 :(得分:1)

您似乎已将参数定义放在单独的行上。这应该有助于解析源文件。同时将宏名称添加到%MEND语句中,以便您的解析代码可以进行双重检查,确定它没有找到错误的名称。

我还建议将评论块移动到宏中。

%macro assert_exist
(data /* table or list of tables */
);
/*--------------------------------------------------------;
* ASSERT_EXIST                                           ;
* Fails explicitely when a table doesn't exist           ;
* Accepts a list of tables as input                      ;
*--------------------------------------------------------;
EXAMPLES
%assert_exist(not_a_table);   * prints explicit error and aborts;
%assert_exist(sashelp.class); * does nothing;
%assert_exist(sashelp.cars not_a_table sashelp.class); * prints explicit error and aborts;
*/
%local i table;
%do i=1 %to %sysfunc(countw(&data,%str( )));
  %let table = %scan(&data,&i,%str( ));
  %if not %sysfunc(exist(&table)) %then %do;
    %put ERROR: Table &table doesnt exist!;
    %abort;
  %end;
%end;
%mend assert_exist;