BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
seanp
Calcite | Level 5

Hello,

 

I am trying to increment a macro variable, and keep getting the "A character operand was found in the %eval function or %if condition where numeric expected....

 

**create an incrementer, so you can rank things, and some macro variables, for rank creation;
%global nihssbrankvar ninetyrankvar rank3mrankvar;
%let rank3mrankvar = 1;
%let ninetyrankvar = 1;
%let nihssbrankvar = 1;

 

**macro to increment my macrovariables;

%macro incrementvar(vartoincrement);
%let vartoincrement = %eval(&vartoincrement. + 1);
%mend;


**now lets generate a ranking for everyone, based on their rankin 3 month score;
proc sort data=mydata;
by rank3m;
run;

 

**now, let's apply this ranking;

data myranked;
set mydata;
by rank3m;

 

rank3m_rank = &rank3mrankvar.;

 

if last.rank3m=1 then do;
%incrementvar(rank3mrankvar);
charRank3m = put(last.rank3m, 8.); *This is just a test line, to ensure that last.Rank3m is flagging when i expect it is;

 

end;


run;

 

ugh I've been literally beating my head on a wall for a day, it is causing me some serious anxiety.

 

There are a couple of other posts I have found, which helped point me towards using %eval in the first place (for example) but were not like my issue and I was unable to apply to my own. I want to simply increment an integer macro variable whenever I want to, and my macro to do so is expecting an integer? But, i verify in a datastep that my macro variable rank3m_rank (which is being set equal to my macro varible I am trying to increment, &rank3mrankingvar., is indeed a numeric and not a char)

 

Thanks so much

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Let's just look at your stated objective of creating a utility macro that will increment a given macro variable by one and ignore the irrelevant data step code as just part of your attempt to debig your problem.  Here is your proposed macro definition

%macro incrementvar(vartoincrement);
  %let vartoincrement = %eval(&vartoincrement. + 1);
%mend;

The %LET statement looks fine if you just wanted to increment a variable named VARTOINCREMENT.  But if you are trying to create a macro takes as input the Name of a macro variable that you want to increment then you need to change this code becuase it is currently trying to add one to the NAME of the macro variable and store the result back into the macro variable that holds the input to the macro.

 

What you did was like this:

%let X=1;
%let NAME=X;
%let NAME = %EVAL(X + 1);

So first you are trying to add one to the string X, which won't work.  To fix that we need to use the vlaue of macro variable whose name is the value of the macro variable NAME.  To do that we need to use &&&NAME.

 

Then you are trying to store the result back into the variable NAME instead of into the variable  X.  To fix that we need to replace NAME with &NAME. 

 

So now your macro looks like this:

%macro incrementvar(vartoincrement);
  %let &vartoincrement = %eval(&&&vartoincrement. + 1);
%mend;

 

View solution in original post

5 REPLIES 5
Reeza
Super User

Is your %let statement missing an & on the first reference to the macro variable?

ballardw
Super User

I suspect your issue is with this:

%incrementvar(rank3mrankvar);

 

the macro is processing the text value rank3mrankvar.

You may have meant

%incrementvar(&rank3mrankvar);

 

I would seriously examine the whole process as using a macro variable to set values inside a data step is likely not doing what you think it is.

The data step compiles with values found the first time, it does NOT increment and recompile with a changed value.

 

I think that you may be attempting to create a convoluted RETAIN.

Is something like this what your attempting to accomplish?

data myranked;
   set mydata;
   by rank3m;
   Retain  rank3m_rank  1;
   if last.rank3m=1 then do;
     Rank3m_rank +1;
     charRank3m = put(last.rank3m, 8.); *This is just a test line, to ensure that last.Rank3m is flagging when i expect it is;
   end;
run;
FreelanceReinh
Jade | Level 19

I think, the reason for the error message "A character operand was found ..." is the incorrect macro definition, as Reeza had noticed already. Indeed, there were three ampersands missing:

%macro incrementvar(vartoincrement);
%let &vartoincrement = %eval(&&&vartoincrement + 1);
%mend;

/* Test the macro */
%let testmv=16;
%incrementvar(testmv);
%put &=testmv;

But I fully agree with ballardw that you probably don't even need this macro, because it wouldn't help you anyway in a data step. Most likely you'll be better off limiting your program to non-macro code.

Kurt_Bremser
Super User

Before you waste further brain cycles, consider this:

 

A macro will always execute before the data step runs (or after the data step, if you call it with call execute), so the incrementation of a macro variable will happen before your datastep code executes at all.

But you can generate valid data step incrementation code dynamically with a macro, if you need to respond to conditions that exist before said data step is reached.

 

So my best guess is that you do not need a macro at all, unless you have identical code that is used in several data steps, or need to iteratively run the step(s).

Tom
Super User Tom
Super User

Let's just look at your stated objective of creating a utility macro that will increment a given macro variable by one and ignore the irrelevant data step code as just part of your attempt to debig your problem.  Here is your proposed macro definition

%macro incrementvar(vartoincrement);
  %let vartoincrement = %eval(&vartoincrement. + 1);
%mend;

The %LET statement looks fine if you just wanted to increment a variable named VARTOINCREMENT.  But if you are trying to create a macro takes as input the Name of a macro variable that you want to increment then you need to change this code becuase it is currently trying to add one to the NAME of the macro variable and store the result back into the macro variable that holds the input to the macro.

 

What you did was like this:

%let X=1;
%let NAME=X;
%let NAME = %EVAL(X + 1);

So first you are trying to add one to the string X, which won't work.  To fix that we need to use the vlaue of macro variable whose name is the value of the macro variable NAME.  To do that we need to use &&&NAME.

 

Then you are trying to store the result back into the variable NAME instead of into the variable  X.  To fix that we need to replace NAME with &NAME. 

 

So now your macro looks like this:

%macro incrementvar(vartoincrement);
  %let &vartoincrement = %eval(&&&vartoincrement. + 1);
%mend;

 

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 5 replies
  • 24711 views
  • 9 likes
  • 6 in conversation