BookmarkSubscribeRSS Feed
aj34321
Quartz | Level 8

Hi All,

 

I want to run something like below. 

Any simple way to run %if &var_Status. not in ('XP','XC','TP') %then %do;

 

Below is the error what I get-

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: "&var_LastCampaignSetStatusCode." not in :('XP','XC','TP')
ERROR: The macro CHECKCONTROL will stop executing.

 

 

%macro CheckControl;
/*Get the status of previous campaign load*/
proc sql;
select ID, Status
into :var_ID, :var_Status
from SomeTable
having ID = max(ID);
quit;

%if &var_Status. not in ('XP','XC','TP') %then %do;
/*Do something*/
%end;
%else %do;
/*Do something else*/
%end
%mend CheckControl;
%CheckControl;

7 REPLIES 7
Astounding
PROC Star

Macro language does contain an IN operator, but it is extremely tricky.  I would recommend just spelling out the conditions in this case:

 

%if (&var_Status ne XP) and (&var_Status ne XC) and (&var_Status ne TP) %then %do;

mkeintz
PROC Star

How about

 

%if %sysfunc(findw(XP|XC|TP,&varstatus,|))=0 %then %do;

or

%if %sysfunc(findw(%str(XP,XC,TP),&varstatus,%str(,)))=0 %then %do;

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Kurt_Bremser
Super User

Since the macro processor only knows one data type (text), quotes are not necessary and wrong in most places. You also must not use commas to separate the values in your list.

For the use of your intended construct, see http://support.sas.com/kb/31/322.html

Note the / minoperator option in the %macro statement.

So define your macro like that:

%macro checkcontrol / minoperator;

.
.
.

%if not(&var_Status. in XP XC TP) %then %do;

.
.
.

%mend;
chinli72
Obsidian | Level 7

This structure works. Thank you.

bing2202
Calcite | Level 5

I use the same structure and get error message. Could you please let me which part goes wrong in my code? Thanks a lot.

 

%macro loop_thru_fcat_list;
    %local i next_name;
    %let i=1;
    %do %while (%scan(&fcat_name, &i) ne );
       %let next_name = %scan(&fcat_name, &i);
       %if not(&NEXT_NAME. in C1_EST FIBRINO) %then %do;
          %cbs_fcat(&NEXT_NAME);
       %end;
       %let i = %eval(&i + 1);
    %end;
%mend loop_thru_fcat_list;

 

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: not(&NEXT_NAME. in C1_EST FIBRINO)
ERROR: The macro LOOP_THRU_FCAT_LIST will stop executing.

Tom
Super User Tom
Super User

You have to tell SAS that you want the macro processor to treat the text IN as an operator.  You also need to tell it what delimiter to use between the items in the list. 

%macro loop_thru_fcat_list / minoperator mindelimiter=' ';

You also have to watch out for text like OR that might be confused for an operator. So use %QSCAN() instead of %SCAN().

Also your macro is referencing a macro variable that is neither an input nor a local macro variable. Much better to be explicit about the source of the inputs.

%macro loop_thru_fcat_list(fcat_name) / minoperator mindelimiter=' ';
%local i next_name;
%do i=1 %to %sysfunc(countw(&fcat_name));
   %let next_name = %qscan(&fcat_name, &i);
   %if not(&NEXT_NAME. in C1_EST FIBRINO) %then %do;
     %PUT &=i &=NEXT_NAME ;
   %end;
%end;
%mend loop_thru_fcat_list;

Let's test it:

11    %loop_thru_fcat_list(a or b);
I=1 NEXT_NAME=a
I=2 NEXT_NAME=or
I=3 NEXT_NAME=b

If we use %SCAN() instead of %QSCAN() you can see the error:

12    %macro loop_thru_fcat_list(fcat_name) / minoperator mindelimiter=' ';
13    %local i next_name;
14    %do i=1 %to %sysfunc(countw(&fcat_name));
15       %let next_name = %scan(&fcat_name, &i);
16       %if not(&NEXT_NAME. in C1_EST FIBRINO) %then %do;
17         %PUT &=i &=NEXT_NAME ;
18       %end;
19    %end;
20    %mend loop_thru_fcat_list;
21
22    %loop_thru_fcat_list(a or b);
I=1 NEXT_NAME=a
ERROR: Operand missing for IN operator in argument to %EVAL function.
ERROR: The macro LOOP_THRU_FCAT_LIST will stop executing.
RW9
Diamond | Level 26 RW9
Diamond | Level 26

This is matter of perspective really.  You can simply the problem down to:

%macro CheckControl();
  ...
%mend CheckControl;

data _null_;
  set sometable;
  by id;
  if last.id and var_status in ('XP','XC','TP') then 
    call execute('%CheckControl;');
run;

Assumes sorted.  In fsct, depending on the previous code the above may not be necessary at all.  Quite a lot of the conditional macro logic is just put in programs due to the process being badly thought out, or previous decisions making processing further down a program harder than they need to be.

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
  • 7 replies
  • 11999 views
  • 4 likes
  • 8 in conversation