Hello
In this example mon=1712 and I want to create automatic sas macro that get value of 1 month before 1712 ( 1711).
I get value 1681 for macro var mon_minus1.
What is the way to get value 1711???
%let mon=1712;
%let mon_minus1=%sysfunc(intnx(month,&mon.,-1,s));
%put &mon_minus1.;
Here some spaghetti for you:
options yearcutoff=1926;
%let have=1712;
%let want=%sysfunc(intnx(month,%sysfunc(inputn(1712,yymmn4.)),-1),yymmn4.);
%put &=want;
WANT=1711
is 1712 the actual numeric value of mon? Or is it a formated date value?
data _null_;
mon=1712;
mon_minus1=input(put(intnx('month', input(put(mon, $4.), yymmn4.), -1, 'b'), yymmn4.), 4.);
call symputx('mon_minus1', mon_minus1);
run;
%put &mon_minus1.;
It is great but I want to learn how to do it with open code %let
Also in your code there is a warning
WARNING: Variable mon has already been defined as numeric.
@Ronein wrote "I want to learn how to do it with open code %let" then
the code
data _null_;
date_in = input("20&mon.01", yymmdd8.);
date_out = intnx('month', date_in, -1); /* default day is 01 */
call symput('mon_minus1', strip(date_out));
run;
%put &mon_minus1;
can be written as:
%let mon = 1702; /* macro variable is always a charcter string */
%let date_num = %sysfunc(input("20&mon.01", yymmdd8.));
%let date_out = %sysfunc(intnx(month,&date_num, -1));
%let mon_minus1 = %substr(%sysfunc(put(date_out,yymmdd8.)), 3,4);
%put &mon_minus1;
1) What date is 1712 ? is it DEC 2017 ? or just a sequence number?
2) For sequence number use code:
%let prev = %eval(&mon -1);
3) Function INTNX requires a sas date. In case 1712 is DEC 2017 use next code:
data _null_;
date_in = input("20&mon.01", yymmdd8.);
date_out = intnx('month', date_in, -1); /* default day is 01 */
call symput('mon_minus1', strip(date_out));
run;
%put &mon_minus1;
Sorry that I didn't say.
1712 is Dec 2017
I know how to do it within a data step(Way1 is clear for me but I don't know how to do it in way2)
%let mon=1712;/*YYMM*/
/*Way1*/
data _NULL_;
date_in = input("&mon.", yymmn4.);/*SAS date*/
date_out = intnx('month', date_in, -1); /* default day is 01 */
date_out_b=put(date_out,yymmn4.);
call symput('mon_minus1_a', strip(date_out));
call symput('mon_minus1_b', strip(date_out_b));
run;
%put &mon_minus1_a;/*21124*/
%put &mon_minus1_b;/*1711*/
/*Way2*/
%let mon_minus1_a=%sysfunc(inputn(&mon. ,yymmn4.));/*SAS date*/
%put &mon_minus1_a.;/*21154*/
Here some spaghetti for you:
options yearcutoff=1926;
%let have=1712;
%let want=%sysfunc(intnx(month,%sysfunc(inputn(1712,yymmn4.)),-1),yymmn4.);
%put &=want;
WANT=1711
Have you tried the code:
%let mon = 1712; /* macro variable is always a charcter string */
%let date_num = %sysfunc(input("20&mon.01", yymmdd8.));
%let date_out = %sysfunc(intnx(month,&date_num, -1));
%let mon_minus1 = %substr(%sysfunc(put(date_out,yymmdd8.)), 3,4);
%put &mon_minus1;
Sometimes it is easier to split the code into several rows than write it as one complicated statement.
Check each step and be sure you understand it.
How I yearn for the days when life was simple:
%let mon_minus1 = %eval(&mon - 1);
%if %substr(&mon_minus1, 3) = 00 %then %let mon_minus1 = %eval(&mon_minus1 - 88);
If you are working with a slightly older version of SAS that doesn't support %IF %THEN in open code, you could smoosh all the logic together:
%let mon_minus1 = %eval(&mon - 1 - 88 * (%substr(&mon, 3)=01) ) ;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.