BookmarkSubscribeRSS Feed
Ronein
Onyx | Level 15

Hello

In this example the user enter two dates (start and end in format YYMM) .

The target is to get all end of quarter months between start and end.

for example:

start=1612

end=1808

We should get  1612  1703  1706  1709  1712  1803  1806

 

In the following code the problem is that we get also 1809 (which is bigger than end )

 

One more problem is that when I run %PUT &&m&n..;  I get  warning  "WARNING: Apparent symbolic reference M not resolved."

%let start=1612; /*Must start from end of quarter :Dec March June Sep*/
%let end=1807; 

%let date_start=%sysfunc(inputn(&start.,yymmn4.));
%let date_end=%sysfunc(inputn(&end.,yymmn4.));
%put &date_start.;
%put &date_end.;


Data want_month;
do j=0 to intck('QUARTER',&date_start.,&date_end.) ;
ddate=intnx('QUARTER', &date_start., j, 's');
char_ddate = put(ddate, YYMMn4.);
/*Var_Macro_name=compress('m'||put(J,2.));*/
Var_Macro_name='m'||strip(put(J,2.));
call symputx('m'||strip(put(J,2.)), char_ddate);
output;
end;
Run;


PROC SQL Noprint;
select count(*)  INTO:n 	   
	from want_month
;
QUIT;
%put &n.;
%put &m0;
%put &m1;
%PUT &&m&n..;

2 REPLIES 2
Jagadishkatam
Amethyst | Level 16

please try the below i applied the filter

 

new=%sysfunc(inputn(&end.,best.));
if input(char_ddate,best.)<new;

 

 

%let start=1612; /*Must start from end of quarter :Dec March June Sep*/
%let end=1807; 

%let date_start=%sysfunc(inputn(&start.,yymmn4.));
%let date_end=%sysfunc(inputn(&end.,yymmn4.));
%put &date_start.;
%put &date_end.;


Data want_month;
do j=0 to intck('QUARTER',&date_start.,&date_end.) ;
ddate=intnx('QUARTER', &date_start., j, 's');
char_ddate = put(ddate, YYMMn4.);
/*Var_Macro_name=compress('m'||put(J,2.));*/
Var_Macro_name='m'||strip(put(J,2.));
call symputx('m'||strip(put(J,2.)), char_ddate);
new=%sysfunc(inputn(&end.,best.));
if input(char_ddate,best.)<new;
output;
end;
format ddate date9.;
Run;


PROC SQL Noprint;
select count(*)  INTO:n 	   
	from want_month
;
QUIT;
Thanks,
Jag
Kurt_Bremser
Super User

Use a do while loop, it is simpler to read:

%let start=1612;
%let end=1807;

data want_month (keep=quarter);
length quarter $4;
quarterdate = intnx('quarter',input("20&start.01",yymmdd8.),0,'e');
n = 1;
do while (quarterdate le input("20&end.01",yymmdd8.));
  quarter = put(quarterdate,yymmn4.);
  call symputx('m'||strip(put(n,2.)),quarter);
  output;
  quarterdate = intnx('quarter',quarterdate,1,'e');
  n + 1;
end;
run;

%put _global_;

PROC SQL Noprint;
select count(*)  INTO:n 	   
	from want_month
;
QUIT;

%let n=&n; * removes leading blanks;
%put &m1;
%put &&m&n;

Note how to fix the problem with &&m&n. Without the %let n=&n, you see this in the log:

53         %put &&m&n;
WARNING: Apparent symbolic reference M not resolved.
&m       7

The blanks between the letter m and the numeric value in &n are clearly visible.

Note that it is usually simpler to create dynamic code off a dataset than off a bunch of macro variables.

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

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
  • 2 replies
  • 1114 views
  • 1 like
  • 3 in conversation