crlaoy
crlaoy

Reputation: 89

SAS macro mod function callout issue

I'm trying to adjust the reporting period between 1 month and 3 months (full quarter) based on time of the month. Based on the date below, I should be getting the period between 1/1 and 3/31, but I'm getting a logic error when I run the following code, any advice on how to fix it?

ERROR: Expected close parathesis after macro function invocation not found. ERROR: Required operator not found in expression: 0 ) ERROR: SKipping to next %END statement.

%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;   

Upvotes: 1

Views: 272

Answers (1)

Reeza
Reeza

Reputation: 21274

A few more issues than I initially realized so listing all below but overall, you shouldn't be doing this in this manner. Use a data step and CALL SYMPUTX() to create the macro variable at the end instead - less buggy and infinitely easier to code.

  1. EVERY function call in a macro requires the %SYFUNC() wrapped around it - INTNX(), MOD(), MONTH()

  2. Missing semicolons (Line 2, 4, 7, 9)

  3. %DO is spelled incorrectly (DOL)

  4. I don't know what you would want here: &obsdate_current_qtr_first_day You have no macro variable shown with that name but you have two with each portion of the name? Did you want to concatenate those values?

  5. Functions used in macros should not have the parameters within quotes ('month' versus month)

  6. Use the options mprint; when writing/developing macros so you can see the values in the log and get more information to help you debug the issues at hand.

     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;
    

EDIT: Here's a data step solution that can be simplified once you have it set up for what you want.

    %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.;

Upvotes: 1

Related Questions