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..;
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;
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.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.