BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Michelle_
Fluorite | Level 6

Hi all, i have write the macro as shown below.

Initially, I direct put the begin date and end date (example stated in orange font below). The macro manages to run. 

However, for ease of efficiency in future, I would like to set a formula to indicate the begin date and end date.  But, it pops the error as below.

 

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 
       &dif 
ERROR: The %TO value of the %DO I loop is invalid.
ERROR: The macro DATECREATE will stop executing.

 

%let Period = 202304;
%let Month  = 4;

%macro month_setting();
    %global begin end;

    %if %sysevalf(&month = 4) %then 
        %do;		
	    %let begin		= put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -6), date9.);
	    %let end		= put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -1), date9.);
/*	    %let begin 		= 01OCT2022;*/
/*	    %let end 		= 01APR2023;*/
        %end;
	%else %if %sysevalf(&month = 13) %then
        %do;
	    %let begin		= put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -13), date9.);
	    %let end		= put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -1), date9.);
/*	    %let begin 		= 01JAN2022;*/
/*	    %let end 		= 01APR2023;*/
        %end;

%mend month_setting;
%month_setting();

%macro datecreate;
	%let startdate  = %sysfunc(inputn(&begin,anydtdte9.));
	%let enddate	= %sysfunc(inputn(&end,anydtdte9.));
	%let dif	= %sysfunc(intck(MONTH,&startdate,&enddate)); 
		%do i=0 %to &dif;
			%global date_&i;
			%let date_&i=%sysfunc(intnx(month,&startdate,&i,B),yymmn6.);
			%put &&date_&i;
		%end;
%mend;
%datecreate;

Would like to seek for help to solve the issue. Thanks in advance! 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Simple enough to analyze.

 

Start with the error.  The only way &DIF is not value is if the result of the function call that created it is a missing value.

 

So look at the arguments to that function call.

%let dif = %sysfunc(intck(MONTH,&startdate,&enddate)); 

The first one is fine.  

So where did those two macro variable get created?  There are two choices, but they both follow the same (incorrect) pattern.

%let begin = put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -6), date9.);
%let end = put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -1), date9.);

The answer is obvious. You are setting BEGIN and END to strings that start with the letters PUT.  Those cannot be a valid number to pass to the INTNX() function.

 

You clearly understand that you have to use %SYSFUNC() to call SAS functions in macro code because you used it when trying to make the macro variable DIF.  So you need to use it when making BEGIN and END also.

%let begin = %sysfunc(intnx(month,%sysfunc(inputN(&period.01,yymmdd10.)),-6));
%let end = %sysfunc(intnx(month,&begin,+5));

Do not FORMAT the values with the DATE9. format if the goal is to use them as DATE values (and not text strings for humans to read).  But if you did set the macro variables to strings like 01JAN2023 then to use them as actual date values you would need to add quotes and the letter D to create date literals.

%let begin = "%sysfunc(intnx(month,%sysfunc(inputN(&period.01,yymmdd10.)),-6),date9.)"d;
%let end = "%sysfunc(intnx(month,&begin,+5),date9.)"d;

View solution in original post

3 REPLIES 3
Tom
Super User Tom
Super User

Simple enough to analyze.

 

Start with the error.  The only way &DIF is not value is if the result of the function call that created it is a missing value.

 

So look at the arguments to that function call.

%let dif = %sysfunc(intck(MONTH,&startdate,&enddate)); 

The first one is fine.  

So where did those two macro variable get created?  There are two choices, but they both follow the same (incorrect) pattern.

%let begin = put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -6), date9.);
%let end = put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -1), date9.);

The answer is obvious. You are setting BEGIN and END to strings that start with the letters PUT.  Those cannot be a valid number to pass to the INTNX() function.

 

You clearly understand that you have to use %SYSFUNC() to call SAS functions in macro code because you used it when trying to make the macro variable DIF.  So you need to use it when making BEGIN and END also.

%let begin = %sysfunc(intnx(month,%sysfunc(inputN(&period.01,yymmdd10.)),-6));
%let end = %sysfunc(intnx(month,&begin,+5));

Do not FORMAT the values with the DATE9. format if the goal is to use them as DATE values (and not text strings for humans to read).  But if you did set the macro variables to strings like 01JAN2023 then to use them as actual date values you would need to add quotes and the letter D to create date literals.

%let begin = "%sysfunc(intnx(month,%sysfunc(inputN(&period.01,yymmdd10.)),-6),date9.)"d;
%let end = "%sysfunc(intnx(month,&begin,+5),date9.)"d;
Michelle_
Fluorite | Level 6

It works! Thank you so much.

Kurt_Bremser
Super User

&begin will resolve to the text

put(intnx('month',input(strip(put(&period, 6.)||'01'), yymmdd10.), -6), date9.)

which can not be used as argument for the INPUTN function. Similar for &end.

 

Always keep in mind that a DATA step function will only work in macro language when wrapped in %SYSFUNC.

sas-innovate-white.png

🚨 Early Bird Rate Extended!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9.

 

Lock in the best rate now before the price increases on April 1.

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 3 replies
  • 1259 views
  • 2 likes
  • 3 in conversation