BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
pchappus
Obsidian | Level 7

I'm trying to name my columns _2013Q4 _2014Q1 etc. The code works if I use the commented out section towards the bottom but if I use the code with the _&Paid_Qtr., it says the IF statement is out of order. 

 

%MACRO Create_Shell();
DATA Triangle;
DO n= 1 to &Cols.;
FORMAT
INC_MO MMDDYY10.;
INC_MO = INTNX("MONTH",MDY(MONTH(TODAY()),1,YEAR(TODAY())),n-&Cols.);
_2013Q3 = 0;
OUTPUT;
END;
RUN;

DATA Triangle;
SET Triangle;
%DO s=3 %TO &Cols. - 1 %BY 3;
%LET x = %EVAL(&Cols. - &s. + 1);
%LET t = %EVAL(&s. + 1);
DATA _NULL_;
FORMAT
PAID_QTR YYQ.;
PAID_QTR = INTNX("MONTH",MDY(MONTH(TODAY()),1,YEAR(TODAY())) -1,&s. - &Cols.);
PUT PAID_QTR=;
PAID_QTR2= PUT(PAID_QTR,YYQ.);
PUT PAID_QTR2=;
CALL SYMPUTX('PAID_QTR',PAID_QTR2);
RUN;
%PUT &=PAID_QTR;
IF &x. > _N_ THEN
_&PAID_QTR. = 0;
ELSE _&PAID_QTR. = .;
/* IF &x. > _n_ THEN */
/* _&t. = 0;*/
/* ELSE _&t. = .;*/
%END;
RUN;
%MEND Create_Shell;

OPTIONS MPRINT MLOGIC;
%Create_Shell;
OPTIONS NOMPRINT NOMLOGIC;

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Before you start writing a macro to generate SAS code figure out what SAS code you want to generate.

I looks like you are playing with the same triangle matrix generating step, but now you want to generate variable names that contain dates in them.  So first figure out what code you want to generate.  As I said on your other question you don't need macro code to generate your matrix.  Just use an ARRAY statement.   If you want to make the variable names dynamic then use a macro variable to hold the list of names.  You can use a data step to generate the macro variable.

 

Let's say you want to generate these variables:

array cols Y2018Q4 Y2019Q1 Y2019Q2 ;

You could run this data step to generate a macro variable.

data _null_;
  length varlist $1000;
  do offset=0 to &cols -1 ;
    date = intnx('qtr',today(),offset);
    varlist=catx(' ',varlist,cats('Y',put(date,yyq.)));
  end;
  call symputx('varlist',varlist);
run;

Then your ARRAY statement can be:

array cols &varlist;

View solution in original post

8 REPLIES 8
pchappus
Obsidian | Level 7

&Cols. = 60 currently.

novinosrin
Tourmaline | Level 20

where is the datastep for this part?

 

RUN;
%PUT &=PAID_QTR;
IF &x. > _N_ THEN
_&PAID_QTR. = 0;
ELSE _&PAID_QTR. = .;
/* IF &x. > _n_ THEN */
/* _&t. = 0;*/
/* ELSE _&t. = .;*/
%END;
RUN;

pchappus
Obsidian | Level 7

it is apart of the DATA  Triangle;

 

The first RUN statement ends the DATA _NULL_ and then the RUN at the bottom the code you pasted is supposed to end the DATA Triangle data step.

 

Thanks,

Paul

Reeza
Super User

Nope, when a data step encounters another DATA statement that serves as a RUN and closes the first step. Your RUN statements are incorrectly set and you cannot have nested DATA Steps. 

 

This is more clear when you format your code.

 

%MACRO Create_Shell();
    DATA Triangle;
        DO n=1 to &Cols.;
            FORMAT INC_MO MMDDYY10.;
            INC_MO=INTNX("MONTH", MDY(MONTH(TODAY()), 1, YEAR(TODAY())), n-&Cols.);
            _2013Q3=0;
            OUTPUT;
        END;
    RUN;

    DATA Triangle;
        SET Triangle;

        %DO s=3 %TO &Cols. - 1 %BY 3;
            %LET x = %EVAL(&Cols. - &s. + 1);
            %LET t = %EVAL(&s. + 1);

        DATA _NULL_; *ends data triangle step;
            FORMAT PAID_QTR YYQ.;
            PAID_QTR=INTNX("MONTH", MDY(MONTH(TODAY()), 1, YEAR(TODAY())) -1, 
                &s. - &Cols.);
            PUT PAID_QTR=;
            PAID_QTR2=PUT(PAID_QTR, YYQ.);
            PUT PAID_QTR2=;
            CALL SYMPUTX('PAID_QTR', PAID_QTR2);
        RUN; *ends _null_ step;

        %PUT &=PAID_QTR;
        IF &x. > _N_ THEN _&PAID_QTR.=0; *open invalid data step code;
        ELSE _&PAID_QTR.=.;

        /* IF &x. > _n_ THEN */
        /* _&t. = 0;*/
        /* ELSE _&t. = .;*/
%END;
    RUN;
%MEND Create_Shell;

OPTIONS MPRINT MLOGIC;
%Create_Shell;
OPTIONS NOMPRINT NOMLOGIC;

 


@pchappus wrote:

it is apart of the DATA  Triangle;

 

The first RUN statement ends the DATA _NULL_ and then the RUN at the bottom the code you pasted is supposed to end the DATA Triangle data step.

 

Thanks,

Paul


 

pchappus
Obsidian | Level 7

Okay that makes since, I need to figure out a way to have the loop create the column names without doing a data null step.

 

For some reason, when ever I paste my code it takes away all my formatting I have in the program. 

Tom
Super User Tom
Super User

Use indentation to format your code to make it clearer.  I like the set the indentation of macro statements independently from the indentation of the actual SAS code that the macro is generating.

%macro create_shell();
data triangle;
  do n= 1 to &cols.;
    format inc_mo mmddyy10.;
    inc_mo = intnx("month",mdy(month(today()),1,year(today())),n-&cols.);
    _2013q3 = 0;
    output;
  end;
run;

data triangle;
  set triangle;

%do s=3 %to &cols. - 1 %by 3;
  %let x = %eval(&cols. - &s. + 1);
  %let t = %eval(&s. + 1);

data _null_;
  format paid_qtr yyq.;
  paid_qtr = intnx("month",mdy(month(today()),1,year(today())) -1,&s. - &cols.);
  put paid_qtr=;
  paid_qtr2= put(paid_qtr,yyq.);
  put paid_qtr2=;
  call symputx('paid_qtr',paid_qtr2);
run;

  %put &=paid_qtr;

if &x. > _n_ then_&paid_qtr. = 0;
else _&paid_qtr. = .;

%end;
run;
%mend create_shell;

That way it is easy to see that you have two line data step that does nothing.

data triangle;
  set triangle;

which will end if the %DO loop runs at least once and generates other steps.

 

And also an IF statements detached from any data step at the end of your %DO loop.

if &x. > _n_ then_&paid_qtr. = 0;
else _&paid_qtr. = .;

and an extra RUN statement after the %DO loop.

 

 

Tom
Super User Tom
Super User

Before you start writing a macro to generate SAS code figure out what SAS code you want to generate.

I looks like you are playing with the same triangle matrix generating step, but now you want to generate variable names that contain dates in them.  So first figure out what code you want to generate.  As I said on your other question you don't need macro code to generate your matrix.  Just use an ARRAY statement.   If you want to make the variable names dynamic then use a macro variable to hold the list of names.  You can use a data step to generate the macro variable.

 

Let's say you want to generate these variables:

array cols Y2018Q4 Y2019Q1 Y2019Q2 ;

You could run this data step to generate a macro variable.

data _null_;
  length varlist $1000;
  do offset=0 to &cols -1 ;
    date = intnx('qtr',today(),offset);
    varlist=catx(' ',varlist,cats('Y',put(date,yyq.)));
  end;
  call symputx('varlist',varlist);
run;

Then your ARRAY statement can be:

array cols &varlist;
pchappus
Obsidian | Level 7

I think I will eventually end up going the array route but using this as a learning opportunity to do it the more complicated way.

 

Thanks for the help!

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 1228 views
  • 1 like
  • 4 in conversation