3
votes

Hi I'm trying to define and run a SAS Macro on a Unix Server.

options symbolgen mprint mlogic;
*options nosymbolgen nomprint nomlogic;

rsubmit;

%let trend_MM = 1;
%let run_date = &sysdate.;

/* loop through Trend_MM number of times to retrieve the MTR completed per each month. */
%macro Trend();
%local start_dt;
%local end_dt;
%local i;

/* loop through each month */
%do i = &Trend_MM. %to 0 %by -1;

/* Calculate set start/end dates to start/end of month */
%let start_dt = %qsysfunc(intnx(month,"&run_date."d,%eval(-1*&i.),b),date9.);
%let end_dt = %qsysfunc(intnx(month,"&run_date."d,%eval(-1*&i).,e),date9.);

    /* select MTR claims in month */
    proc sql;
        create table MTR_&i. as
        select a.claim_id_360
              ,a.claim_id_external 
              ,a.timestamp
              /* v02: a) export date part of the timestamp */
              ,datepart(a.timestamp) as timestamp_dt
              ,a.status_data 
              ,a.status_label 
              ,a.RFE_template_name 
              ,a.brand_name
              ,case when b.claim_id_360 is not missing then "Y" else "N" end as MTR_compl
              ,c.MTR_count
              ,b.last_MTR_comp format = ddmmyy10.
        from 
            /* Base population are all claims where final status is not   */
            (
             select distinct *
             from allg360r._travel_rfe_state_change_hist
             (keep = claim_id_360 claim_id_external timestamp status_data status_label RFE_template_name brand_name)
             where datepart(timestamp) between "&start_dt."d and "&end_dt."d
             group by claim_id_360 
             having timestamp = max(timestamp) and strip(upcase(status_label)) ne "Move to Review"
            ) a

            left join 
        /*     subset with claims that have had a  status in the reference period to obtain  */
        /*     claims that have had such status completed in the period.                                     */
        /*     Also retrieve date of last MTR completed                                                      */
            (
             select distinct claim_id_360, datepart(timestamp) as last_MTR_comp
             from allg360r._travel_rfe_state_change_hist
             (keep = claim_id_360 claim_id_external timestamp status_data status_label RFE_template_name brand_name)
             where (datepart(timestamp) between "&start_dt."d and "&end_dt."d) and status_label = "Move to Review"
             group by claim_id_360
             having timestamp = max(timestamp)
            ) b
            on a.claim_id_360 = b.claim_id_360

            left join 

        /*   Add count of how many since inception of claim  */
        /* v02: b) count how many times in MTR since beginning */
            (
             select distinct
                    claim_id_360
                   ,count(claim_id_360) as MTR_count
             from allg360r._travel_rfe_state_change_hist
             (keep = claim_id_360 claim_id_external timestamp status_data status_label RFE_template_name brand_name)
             where status_label = "Move to Review"
             group by claim_id_360
            ) C
            on a.claim_id_360 = c.claim_id_360
        ;
        quit;

    /* create/append to dataset of all months */

    %if &i. = &trend_MM. %then 
      %do;
        proc sql;
            drop table work.MTR;
            create table work.MTR like work.MTR_&i.;
        quit;
      %end;

    proc append base = work.MTR data = work.MTR_&i.;
    run;
%end;

%mend Trend;

%trend

endrsubmit;

It seems to be working fine but I keep getting this error in the log:

995 endrsubmit; ---------- 180

ERROR 180-322: Statement is not valid or it is used out of proper order.

The error seems to disappear if I put a semicolon after the macro invocation. This doesn't make sense to me because the macro ends with a run; and putting a semicolon after invocation shouldn't make any difference.

Any ideas why this is happening?

2
no clue. probably the interplay between the remote submit and the macro facility, but I cannot explain it. easiest to just add the ; and move on.DomPazz
I'd also encourage using a semicolon to terminate lines that only consist of a single macro call. It makes the code easier for others to read - just like putting a full stop at the end of every sentenceRobert Penridge
Images of text like the Log Error aren't searchable, nor are they accessible. Please edit the question and replace the image with the text of the error and format it as a quotation. To format as a quotation you can put a > ahead of the text. To preserve line endings you can put two spaces at the end of a line in the quotation.Jason Aller

2 Answers

2
votes

The reason is - you defined your macro with brackets ()

Add some brackets to the invocation and it will execute without a semicolon.

%trend()

2
votes

Believe it or not, because you defined your macro with an empty parameter list:

%macro Trend();
  %put TREND running;
%mend trend;

When you try to call the macro like %trend SAS is expecting you to send it a list of parameters, even an empty list will suffice. So the macro call has not ended. The semicolon will end the macro call, but you are right that it is not needed, an is a bad habit to add extra semicolons. When you call a macro that has a parameter list defined (even in this case, has 0 parameters the parentheses were on the macro definition so the list is still defined in some sense), you can invoke it like %trend() . The parentheses end the macro call.

With PC SAS, you can test this nicely by highlighting just %trend and submitting it. The macro will not run. Then if you submit () the macro will run.

Update: Since correcting the macro invocation didn’t work, I suspect it may be a bug in how the word scanner recognizes the endrsubmit statement. Assuming it’s replicable, I would probably add a comment which provides a semicolon. At least that way it’s clear that the semicolon is not part of ending the macro invocation. Sorry I can’t test as don’t have SAS/connect available.

Something like:

* endrsubmit needs a semicolon before it ??? ;
endrsubmit ;