DATA Step, Macro, Functions and more

Strange %eval error

Accepted Solution Solved
Reply
Frequent Contributor
Posts: 105
Accepted Solution

Strange %eval error

Hey guys,

Ok so I have this code to calculate months between a numeric date range:

Example:

%let start_month = 200201;

%let end_month = 201301;

%let second_end_month = 201212;

%let start_yr = %eval(&start_month. / 100);

%let end_yr = %eval(&end_month. / 100);

%let start_mod = %modulo(&start_month.,100);

%let end_mod = %modulo(&end_month.,100);

%let yr_dif = %eval(&end_yr. - &start_yr.);

%let nmonths = %eval(12 * &yr_dif.);

%let temp1 = %eval(&nmonths - &start_mod.);

%let temp2 = %eval(&temp1 + &end_mod.);

%let num_observations = %eval(&temp2 + 1);

This is within a macro being called within my program, which sets different date ranges dependent on the current data being processed.

When I run this selection of code, it runs fine, and outputs the correct value when I check witha %put statement (133). However When I just run my entire program (which has been operating for some time without error, and this is the only piece of code added since), I receive the error:

" ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand

       is required. The condition was: 132 - 1;

ERROR: The macro SET_PRODUCT_SPECIFICS will stop executing. "

I don't understand this error, I don't understand why it is occuring in the same piece of code when run with the entire program, but not when the selection is run alone, also I don't see why "132-1" is not valid input for %eval().

Any help is greatly appreciated. Thanks!

-Ryan


Accepted Solutions
Solution
‎05-16-2013 07:58 PM
Super User
Posts: 5,092

Re: Strange %eval error

Right issue, right solution.  You might be seeing how this plays out, but I'm not sure.  Inside a macro, the condition is %eval(132-1Smiley Wink

Outside a macro, the condition is %eval(132-1)

In both cases, the original code generates something like:

%let start_mod = %eval( (201201 - 201201/100 * 100);;

I've taken out all the extra %evals, since they are not really needed.  But the difference is this.  Outside of a macro, the first semicolon ends the %let statement.  The second just becomes a null statement.  Inside a macro, the second semicolon ends the %let statement.  The first becomes part of the value of &START_MOD.

View solution in original post


All Replies
PROC Star
Posts: 7,364

Re: Strange %eval error

What is %modulo?  Is it another macro?

Frequent Contributor
Posts: 105

Re: Strange %eval error

Yes, it is:

%macro modulo(a, b);                 

%eval(&a - %eval(%eval(&a/&b) * &b));

%mend; 

But we can see that that macro is not the issue because all of the lines execute properly up until

%let temp1 = %eval(&nmonths - &start_mod.); - which actually throws the error, after the preceding statement have resolved (if the modulo function did not work it wouldn't be passing in "132-1" on the error line, which are correct numbers from the preceding calculations.

PROC Star
Posts: 7,364

Re: Strange %eval error

Remove the semi-colon, in the modulo macro, in it's %eval line.  i.e., make it:

%macro modulo(a, b);                

%eval(&a - %eval(%eval(&a/&b) * &b))

%mend;

Super User
Posts: 5,092

Re: Strange %eval error

In light of everything, does the code work fine when you run it in open code, but cause problems when you run it inside a macro definition?

PROC Star
Posts: 7,364

Re: Strange %eval error

: That is why I recommended that the OP remove the semicolon from within the function style macro that the initially posted set of %let statements .. inside a macro .. returns an error: The condition was: 132 - 1;

a %eval of 132-1;   will fail in a macro even though it would work in open code.  The semicolon at the end of the one line in the modulo macro will cause it to fail when called from within a macro.  If the OP removes it, it will work both in open code and in a macro.

Solution
‎05-16-2013 07:58 PM
Super User
Posts: 5,092

Re: Strange %eval error

Right issue, right solution.  You might be seeing how this plays out, but I'm not sure.  Inside a macro, the condition is %eval(132-1Smiley Wink

Outside a macro, the condition is %eval(132-1)

In both cases, the original code generates something like:

%let start_mod = %eval( (201201 - 201201/100 * 100);;

I've taken out all the extra %evals, since they are not really needed.  But the difference is this.  Outside of a macro, the first semicolon ends the %let statement.  The second just becomes a null statement.  Inside a macro, the second semicolon ends the %let statement.  The first becomes part of the value of &START_MOD.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 6 replies
  • 271 views
  • 6 likes
  • 3 in conversation