Macros 用于递增日期的sas宏

Macros 用于递增日期的sas宏,macros,sas,Macros,Sas,我的代码是: libname " Cp/mydata" options ; %let yyyymmdd=20050210; %let offset=0; %let startrange=0; %let endrange=0; /* MACRO FOR INCREMENTING THE DATE */ %macro base(yyyymmdd=, offset=); %local date x ds; /* declare macro variables with local scope */

我的代码是:

libname " Cp/mydata"
options ;
%let yyyymmdd=20050210;
%let offset=0;
%let startrange=0;
%let endrange=0;

/* MACRO FOR INCREMENTING THE DATE */
%macro base(yyyymmdd=, offset=);
%local date x ds; /* declare macro variables with local scope */
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                   ,%substr(&yyyymmdd,7,2)
                   ,%substr(&yyyymmdd,1,4))); /* convert yyyymmdd to SAS date */
%let loopout=100;/* hardcoded - number of times to check whether ds exists */
%do x=&offset %to &loopout; /* begin loop */
   /* convert &date to yyyymmdd format */
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&offset),yymmddn8.); 
   %if %sysfunc(exist( &ds )) %then %do;
      %put &ds exists!;
      &ds /* write out the dataset, if it exists */
      %let x=&loopout; /* exit loop */
   %end;
   %else %do;
      %put &ds does not exist - checking subsequent day;
      %let date=&date+1;
   %end;
%end;
%mend;

%macro loop(yyyymmdd=, startrange=, endrange=);
%local date x ds;
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                      ,%substr(&yyyymmdd,7,2)
                      ,%substr(&yyyymmdd,1,4)));
data x;
set set %base(yyyymmdd=&yyyymmdd, offset=0)
/* loop through each specific dataset, checking first whether it exists.. */
%do x=&startrange %to &endrange;
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&x),yymmddn8.);
   %if %sysfunc(exist( &ds )) %then %do;
      &ds
   %end;
%end;
;
run;
%mend; 
这是我试图运行此宏时产生的错误

数据温度

58集%loop(yyyyymmdd=&yyyymmdd,startrange=&startrange, 58!endrange=&endrange)

错误:文件WORK.DATA.DATA不存在

错误:文件WORK.X.DATA不存在

AQ.CO_20050210不存在-检查第二天

AQ.CO_20050211不存在-检查第二天

AQ.CO_20050212存在

注意:由于错误,系统停止处理此步骤

我需要两方面的帮助:

1) 在这里,如果我的原始数据集中没有日期,我会尝试将日期增加1或2左右。请帮助使此宏正常工作

2) 我希望在我的数据中有另一列ie work.date,该列的值为0或1(如果原始数据中存在指定的日期yyyymmdd,则为1;如果我递增,则为0)。请在我的宏中进行指定的更改。
提前谢谢

在我看来,您的解决方案相当复杂。 但我相信至少有一个问题是我们的第二个宏(%loop)中的变量x:我看不出在哪里定义它

如果不需要限制循环,您可能可以更轻松地完成所有这一切。如果只需要偏移量以外的所有数据集,可以通过使用SASHELP库查找所需的数据集来简化所有这一切。然后循环这个结果

下面不推荐的回复,误读了需求 您正在部分改造控制盘,深入了解intnx和intck函数。

我不太确定您的
%base()
宏到底想要实现什么,但我注意到了一些事情

首先尝试打开
选项mprint以帮助调试。如果您仍然需要更多调试信息,也可以尝试打开以下选项(我建议每次打开1个选项,直到您知道需要哪些选项为止):

选项symbolgen macrogen mlogic

第二,您的示例代码中有
set
,而不是
set
。我认为这对任何人都没有帮助

当我在我的机器上快速尝试代码时,我注意到在调用
%base()
宏时出现了一个奇怪的错误(与您的不同)。这似乎是一个不应该发生的错误,因此我将调用包装在一个
%unquote()
函数中,以确保我收到了您的帖子中提到的错误。您也可以尝试以下方法:

set %unquote(%base(yyyymmdd=&yyyymmdd, offset=0))
通常不需要
%unquote()
函数,除非您显式使用宏引用函数并出现奇怪的错误,但SAS宏有时似乎有自己的想法。我只在知道需要的时候才加上这个

此外,您的libname调用在行尾缺少分号

最后,给出了使用SAS宏语言处理日期的一些建议。不要一直在日期值和格式化值之间转换。它将使你的代码更大,更容易出错,更难阅读。我知道,因为我以前也是这样做的。请尝试始终使用包含实际日期值的变量(通过使用来自
%sysfunc(mdy())
)的结果),然后如果需要格式化的值,请创建一个新变量(例如
%let yyyymmdd=%sysfunc(putn(&mydate),yymmddn8);
。在将值从一个宏传递到另一个宏时,不要传递格式化的值,即使这看起来更容易,也要传递实际值

进行上述更改将删除我的计算机上的所有错误。最终代码:

libname " Cp/mydata";

%let yyyymmdd=20050210;
%let offset=0;
%let startrange=0;
%let endrange=0;

/* MACRO FOR INCREMENTING THE DATE */
%macro base(yyyymmdd=, offset=);
%local date x ds; /* declare macro variables with local scope */
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                   ,%substr(&yyyymmdd,7,2)
                   ,%substr(&yyyymmdd,1,4))); /* convert yyyymmdd to SAS date */
%let loopout=100;/* hardcoded - number of times to check whether ds exists */
%do x=&offset %to &loopout; /* begin loop */
   /* convert &date to yyyymmdd format */
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&offset),yymmddn8.); 
   %if %sysfunc(exist( &ds )) %then %do;
      %put &ds exists!;
      &ds /* write out the dataset, if it exists */
      %let x=&loopout; /* exit loop */
   %end;
   %else %do;
      %put &ds does not exist - checking subsequent day;
      %let date=&date+1;
   %end;
%end;
%mend;

%macro loop(yyyymmdd=, startrange=, endrange=);
%local date x ds;
%let date=%sysfunc(mdy(%substr(&yyyymmdd,5,2)
                      ,%substr(&yyyymmdd,7,2)
                      ,%substr(&yyyymmdd,1,4)));
data x;
set %unquote( %base(yyyymmdd=&yyyymmdd, offset=0))
/* loop through each specific dataset, checking first whether it exists.. */
%do x=&startrange %to &endrange;
   %let ds=AQ.CO_%sysfunc(intnx(day,&date,&x),yymmddn8.);
   %if %sysfunc(exist( &ds )) %then %do;
      &ds
   %end;
%end;
;
run;
%mend; 
%loop(yyyymmdd=&yyyymmdd, startrange=&startrange, endrange=&endrange);

我也试过了,但我无法理解,因为我是sas的新手。如果我在我的第一个宏中将日期设置为全局。它会起作用吗?仍然不起作用。我也尝试过所有组合。你能用一些简单的形式翻译我的代码吗?或者你能修改这些代码吗?谢谢你的建议,伙计。这将在将来对我有所帮助。但是,复制我的代码时,两次丢失分号和重复集只是一个错误,但我的最终代码中除了%unquote之外还有其他内容。干杯,伙计!!这很有效,我也找到了另一种方法。你能看看我问题的第二部分吗?谢谢