如何为sas数据集中的每个观测值执行宏?

如何为sas数据集中的每个观测值执行宏?,sas,sas-macro,Sas,Sas Macro,这是宏代码 libname myfmt "&FBRMrootPath./Formats"; %macro CreateFormat(DSN,Label,Start,fmtname,type); options mprint mlogic symbolgen; %If &type='n' %then %do; proc sort data=&DSN out=Out; by &Label; Run; Data ctrl;

这是宏代码

libname myfmt "&FBRMrootPath./Formats";
%macro CreateFormat(DSN,Label,Start,fmtname,type);
options mprint mlogic symbolgen;
%If &type='n' %then %do;
    proc sort data=&DSN out=Out; by &Label;
        Run;
    Data ctrl;
        set Out(rename=(&Label=label &Start=start )) end=last;
        retain fmtname &fmtname type &type;
        output;
    If last then do;
        hlo='O';
        label='*ERROR';
        output;
    End;
Run;
%End;
%Else  %do;
    proc sort data=&DSN out=Out; by &Start;
        Run;
    Data ctrl;
        set Out(rename=(&Start=label &Label=start )) end=last;
        retain fmtname &fmtname type &type;
        output;
    If last then do;
        hlo='O';
        label='*ERROR';
        output;
    End;
Run;
%End;
proc format library=myfmt cntlin=ctrl;
Run;
%Mend CreateFormat;
以下是控制数据集的代码,通过该代码,上述宏应针对数据集的每次观测运行,观测值是宏中变量的输入

Data OPER.format_control;
Input DSN :$12.  Label :$15. Start :$15. fmtName :$8. type :$1. fmt_Startdt :mmddyy. fmt_Enddt :mmddyy.;
format fmt_Startdt fmt_Enddt date9.;
Datalines;
ssin.prd prd_nm prd_id mealnm n . 12/31/9999
ssin.prd prd_id prd_nm mealid c . 12/31/9999
ssin.fac fac_nm onesrc_fac_id fac1SRnm n . 12/31/9999
ssin.fac fac_nm D3_fac_id facD3nm n . 12/31/9999
ssin.fac onesrc_fac_id D3_fac_id facD31SR n . 12/31/9999
oper.wrkgrp wrkgrp_nm wrkgrp_id grpnm n . 12/31/9999
;
像这样的

proc sql;
select catx(',',cats('%CreateFormat(',DSN),Label,Start,fmtname,cats(type,')');
into :formcreatelist separated by ' '
from oper.format_control;
quit;
您可能需要将一些变量放入宏变量中,以获得所需的格式。我在这里使用了有点笨拙的cats/catx组合,你可以在一次中添加一个“,”的cats


这里确实有一个限制-宏变量中总共大约20000个字符。如果结束了,你要么使用CALL EXECUTE,它有一些奇怪的功能,要么你可以将宏调用放入文本文件并%包含它。

有一种更好的方法来实现这一点,而不是选择。。。转换为宏变量。使用以下临时文件:

filename dyncode temp;

data _null_;
   file dyncode;
   set OPER.format_control;
   put '%createformat ....';
run;

%include dyncode;

filename dyncode clear;
该技术不受宏变量32k长度限制的限制

请注意,一定要在%createformat周围使用单引号,以防止SAS在数据步骤编译之前调用宏。您希望在运行%include时运行宏

上面的方法类似于call execute,但是call execute是邪恶的,因为它没有按照预期的顺序执行宏和宏中嵌入的数据/过程代码。避免调用执行


最后,如果您正在运行交互式SAS并使用该技术,则可以使用一个巧妙的技巧进行调试。注释掉最后两行代码-include和clear文件名。运行其余代码后,在命令窗口中输入SAS命令fslist dyncode。这将在您刚刚生成的动态代码上弹出一个记事本视图。您可以查看它并确保达到预期效果。

这里有一个call execute解决方案,只是为了完整起见:

data _null_;
  set OPER.format_control;
  call execute('%CreateFormat(' || DSN || ',' || Label || ',' || Start || ',' || fmtname || ',' || type || ');');
run;

我已经发布了一个示例调用执行解决方案。这会以与解决方案不同的顺序运行宏的迭代吗?调用执行将以解决方案中正确的顺序在宏步骤中运行。所以不用担心。然而,调用执行有时会以意外的顺序运行这一简单事实让我感到害怕,我现在完全是出于原则而避免使用它。下面是一篇讨论这个问题的文章:参见第2/3页的“调用宏的示例”一节。