如何让SAS在每次调用宏时都对其进行编译,而不是手动执行

时间:2019-03-29 13:29:41

标签: sas sas-macro

上下文:我们使用SAS 9.4Enterprise Guide 7.15。当前,我们正在实现一些新的宏,并且当然必须在此过程中进行很多更改。有时更小,有时更大。问题是,为了使更改生效,SAS需要我们手动编译宏代码或重新启动会话,这有点繁琐。

这是主文件(调用所有宏)中的当前设置:

/* Macro options */
     MAUTOSOURCE  sasautos = "<path to macro>" mlogic mlogicnest mprint mprintnest MRECALL

在使用MAUTOSOURCE */ sasautos =""选项时,是否可以在每次调用Macro时告诉SAS实际也编译Macro而不是使用会话存储的Macro?理想情况下,仅当执行主文件(MAUTOSOURCE */ sasautos =""等)的全部代码行时才编译宏,否则应在会话中保留编译后的版本。

我发现这个paper (The Autocall Macro Facility in the SAS for Windows Environment)在结论中指出

  

此后,SAS将使用已经存在的代码   已编译。如果对宏进行了更改,则必须   在更改生效之前再次进行编译。

我希望这并不意味着我必须手动完成。有任何宏选项可以设置吗?

3 个答案:

答案 0 :(得分:3)

如果从WORK中删除了已编译的宏。SASMACRSAS将在您再次调用它时重新编译该宏。

proc catalog c=work.sasmacr;
   *contents;
   delete your-macro-to-recompile.macro;
   run;
   quit;

答案 1 :(得分:3)

对于普通用户,您应该设置更改的发布时间表。发布后,用户将知道他们需要重新启动新会话。

对于正在测试更改的开发人员,他们只需要使用%INCLUDE重新编译宏。因此,如果您知道XYZ宏已更改,则只需运行:

%include maclib('xyz.sas');

或者您可以强行使用它并重新编译自动调用库中的所有宏。

%incldue maclib('*.sas');

您可能会觉得更奇特,可以创建一个宏来清除已编译宏的实际目录。像这样:

%macro clean_autocall;
proc catalog force c=work.sasmacr;
 save clean_autocall /et=macro;
quit;
options mrecall mautosource;
%mend clean_autocall;

但是,如果您使用的是《企业指南》,则有两个问题。

首先,由于某种原因,它使用其他目录来存储已编译的宏。 (为什么?)我认为它是WORK.SASMAC1而不是WORK.SASMACR。

第二个EG将手动编译所需的一堆帮助程序宏。我不确定这些宏的完整列表是否有官方资料?您可以尝试将代码添加到项目中,以在项目启动时根据目录中的条目自动创建列表。这是10年前我在生产环境中尝试使用EG时列出的列表。但我确信它已经过时了。

%let s_eg_save= checkfmt checkhotfix
  eclibassign eclibunassign enterpriseguide gaccessible
  _eg_conditional_dropds
;

答案 2 :(得分:3)

在SAS 9.3中,他们添加了%SYSMACDELETE宏功能。因此,如果您只想让自动调用重新定义单个宏,则可以使用该宏来删除当前定义。

%symacdelete mymacro;

这是一个实用程序宏,它将查询SASHELP.VCATALG视图以在WORK库中查找已编译的宏并将其删除。它具有列出要删除或保留的宏名称的选项。请注意,普通的SAS会话使用WORK.SASMACR来存储已编译的宏。但是SAS / Studio和EG(也许还有其他运行SAS的方式)改用WORK.SASMAC1。

https://github.com/sasutils/macros/blob/master/macdelete.sas

%macro macdelete(delete,keep);
/*----------------------------------------------------------------------------
Remove compiled macros using %SYSMACDELETE macro statement.

Use DELETE parameter to list macro names to delete.
Use KEEP parameter to list macro names to NOT delete.
Calling it with no values will delete all macros not currently running.
----------------------------------------------------------------------------*/
%local libname memname objname objtype fid i;
%do i=1 %to %sysmexecdepth;
  %let keep=%sysmexecname(&i) &keep;
%end;
%if %length(&delete) %then %let delete=and findw("&delete",objname,',','sit');
%let fid=%sysfunc(open( sashelp.vcatalg(keep=libname memname objname objtype
 where=(libname='WORK' and objtype='MACRO' and memname like 'SASMAC_'
   and not findw("&keep",objname,',','sit') &delete))));
%if (&fid) %then %do;
  %syscall set(fid);
  %do %while(0=%sysfunc(fetch(&fid)));
    %put %sysfunc(compbl(Removing &objname from &libname catalog &memname));
    %sysmacdelete &objname;
  %end;
  %let fid=%sysfunc(close(&fid));
%end;
%else %put %qsysfunc(sysmsg());
%mend macdelete;

示例:

3348  %macro test1; %mend;
3349  %macro test2; %mend;
3350  %macro test3; %mend;
3351  %macro test4; %mend;
3352  %macdelete(test1 test3);
Removing TEST1 from WORK catalog SASMACR
Removing TEST3 from WORK catalog SASMACR
3353  %macdelete(keep=test2);
Removing TEST4 from WORK catalog SASMACR

运行SAS / Studio时的示例:

 97         %macro test1; %mend;
 98         %macro test2; %mend;
 99         %macro test3; %mend;
 100        %macro test4; %mend;
 101        %macdelete(test1 test3);
 Removing TEST1 from WORK catalog SASMAC1
 Removing TEST3 from WORK catalog SASMAC1