SAS 宏 mod 函数标注问题

SAS macro mod function callout issue

我正在尝试根据每月的时间将报告期调整为 1 个月到 3 个月(整个季度)。根据下面的日期,我应该得到 1/1 和 3/31 之间的时间段,但是当我 运行 以下代码时出现逻辑错误,关于如何修复它的任何建议?

错误:未找到宏函数调用后预期的关闭对偶。 错误:在表达式中找不到所需的运算符:0) 错误:跳到下一个 %END 语句。

%let obsdate = '31Mar2021'd;
%let current_qtr_first_day = intnx('month', &obsdate, -2, 'B');
%let current_qtr_last_day = intnx('month', &obsdate, 0, 'E');
%let current_month_first_day = intnx('month', &obsdate, 0, 'B');
%let current_month_last_day = intnx('month', &obsdate, 0, 'E');

%if %sysfunc(MOD(month(&obsdate),3)=0 ) %then %do;
    %let startdt = &obsdate_current_qtr_first_day;
    %let enddt = &obsdate_current_qtr_last_day;
%end;
%else %do;
    %let startdt = &obsdate_current_month_first_day;
    %let enddt = &obsdate_current_month_last_day;
%end;   

比我最初意识到的问题多了一些,所以在下面列出了所有问题,但总的来说,您不应该以这种方式这样做。使用数据步骤和 CALL SYMPUTX() 在最后创建宏变量 - 错误更少,编码更容易。

  1. 宏中的每个函数调用都需要 %SYFUNC() 环绕它 - INTNX()MOD()MONTH()

  2. 缺少分号(第 2、4、7、9 行)

  3. %DO 拼写错误 (DOL)

  4. 我不知道您在这里想要什么:&obsdate_current_qtr_first_day您没有显示带有该名称的宏变量,但名称的每个部分都有两个?您要连接这些值吗?

  5. 宏中使用的函数不应在引号内包含参数('month' 与月份)

  6. 使用 options mprint; when writing/developing 宏,以便您可以在日志中查看值并获取更多信息以帮助您调试手头的问题。

     options mprint;
     %let obsdate = '31Mar2021'd;
     %let current_qtr_first_day = %sysfunc(intnx(month, &obsdate, -2, B));
     %let current_qtr_last_day = %sysfunc(intnx(month, &obsdate, 0, E));
     %let current_month_first_day = %sysfunc(intnx(month, &obsdate, 0, B));
     %let current_month_last_day = %sysfunc(intnx(month, &obsdate, 0, E));
     %if %sysfunc(MOD(%sysfunc(month(&obsdate)), 3))=0 %then %do;
     %let startdt = &obsdate._&current_qtr_first_day;
     %let enddt = &obsdate._&current_qtr_last_day;
     %end;
     %else %do;
     %let startdt = &obsdate._&current_month_first_day;
     %let enddt = &obsdate._&current_month_last_day;
     %end;
    

编辑:这是一个数据步骤解决方案,一旦您根据需要对其进行设置,就可以对其进行简化。

    %macro get_report_dates(obsdate=);
            data _null_;
            
            
            *determine if month or quarterly reporting is needed;
            if month(&obsdate) in (3, 6, 9, 12) then interval = 'QTR';
            else interval = 'MONTH';
            
            start_date = intnx(interval, &obsdate, 0, 'b');
            end_date = intnx(interval, &obsdate, 0, 'e');
            format start_date end_date date9.;
            
            *creates global macro variables available outside this macro;
            *change format here to have it displayed as desired (eg date9);
            call symputx('startdt', put(start_date, yymmddd10.), 'g');
            call symputx('enddt', put(end_date, yymmddd10.), 'g');
            run;
            
    %mend;
    
    *test for a quarter;
    %get_report_dates(obsdate="01Mar2021"d);
    %put &startdt.;
    %put &enddt.;
    
    *test for a month;
    %get_report_dates(obsdate="01Feb2021"d);
    %put &startdt.;
    %put &enddt.;