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) ) ;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.