SAS:运行 do 循环内的宏似乎不起作用

SAS: Running macros inside do loop does not seem to work

我需要多次 运行 一系列宏。为此,我构建了一个新的宏,其中包含一个 do-loop,它应该 运行 "i" 次,并且随着 do-loop 的每次迭代,上面引用的一系列宏应该 运行。

这是代码的本质(请注意,第一个过程 sql 本质上取自名为 "DatesRange" 的数据集,并将日期范围放入变量 "varlist_Dates" 中;范围此变量中的日期用于 Macro1、Macro2、Macro3)。

%macro MultipleTimes;

  proc sql noprint;
    select distinct Date
    into :varlist_Dates separated by ' '
    from DatesRange
    order by Date;
  quit; 

  %do i = 1 %to 5;
    %let date = %scan(&varlist_Dates.,&i.);
    %Macro1;
    %Macro2;
    %Macro3;
  %end;

%mend;

我发现它 在 i=1 处停止并且永远不会继续。我完全不清楚为什么。我尝试过删除一些宏并保留其他宏,但似乎没有任何效果。我觉得我的方法可能有一些更基本的东西是关闭的,因为我对 SAS 以及宏内部 do-loop 内部的宏工作方式不了解。

如有任何帮助,我们将不胜感激。谢谢!

首先:检查这些宏中是否使用了 i。我敢打赌。它可能被更改为高于 5 的值(因此在一个循环后退出)。

在 SAS 中,当您引用 已经 存在的宏变量时,它被定义为具有包含它的最局部符号 table 的范围,除非您使用 %local 将其指定为当前宏的本地。因此,如果您在多个嵌套宏中使用 %let i=1 to 5;,它将使用相同的 &i

举个例子,看下面的代码:

%let i=A;
%macro outer;
  %put &=i;
  %do i=1 %to 5;
    %put OUTER FIRST: &=i;
    %inner;
    %put OUTER LAST: &=i;
  %end;
%mend outer;
%macro inner;
  %do i=1 %to 5;
    %put INNER: &=i.;
  %end;
%mend;
%put GLOBAL FIRST: &=i;
%outer;
%put GLOBAL LAST:&=i;

请注意 &i 始终是相同的值。你不是这个意思吧?

现在,另一方面,如果你做得对,&i 确实会在每一位中获得不同的值:

%let i=A;
%macro outer;
  %local i;
  %put &=i;
  %do i=1 %to 5;
    %put OUTER FIRST: &=i;
    %inner;
    %put OUTER LAST: &=i;
  %end;
%mend outer;
%macro inner;
  %local i;
  %do i=1 %to 5;
    %put INNER: &=i.;
  %end;
%mend;
%put GLOBAL FIRST: &=i;
%outer;
%put GLOBAL LAST:&=i;

如果您 %put _all_ 在 INNER 中,您会看到它的实际效果。


第二:不要这样写。你会付出很多努力,只是把它写成一个更好的开始方式。

%Macro RunMyMacros(date=);
  %Macro1;  *I hope you use &date as a parameter in these and not as a global;
  %Macro2;
  %Macro3;
%mend RunMyMacros;

proc sql noprint;
  select distinct cats('%RunMyMacros(date=',Date,')')
  into :calllist_Dates separated by ' '
  from DatesRange
  order by Date;
quit; 


&calllist;

这更易于使用、故障排除和 运行,并且不需要硬编码有效日期的数量或其中的任何其他内容。