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

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

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
  • 1207 views
  • 1 like
  • 3 in conversation