Coding a Macro to tell whether one string is in a string list or not[Code and Log are below].
In one way, it works. But in the other way, it is a BIG NOT. When the String to pass as var with additional space after, the return
value changes from 1 to 0?!!
Anyone helps...
%let vrf_sellist=vrf_ordval_dif_acs_p vrf_ordval_dif_mix_1 vrf_ordval_dif_mix_2 vrf_ordval_dif_p vrf_ordvol_dif_p vrf_ordvol_dif_p_d vrf_val_dif_p;
%macro isin(vlist, var);
%local i isin;
%let n_vars=%sysfunc(countw(&vlist.));
%let isin=0;
%do i=1 %to &n_vars;
%if &var.=%scan(&vlist.,&i) %then %do;
%let isin=1;
%end;
%end;
&isin
%mend;
%isin(&vrf_sellist., vrf_ordval_dif_acs_p); /*=1*/
%isin(&vrf_sellist., vrf_ordnet_dif_acs_p ); /*=0*/
7532 %let vrf_sellist=vrf_ordval_dif_acs_p vrf_ordval_dif_mix_1 vrf_ordval_dif_mix_2
7532! vrf_ordval_dif_p vrf_ordvol_dif_p vrf_ordvol_dif_p_d vrf_val_dif_p;
7533
7534 %macro isin(vlist, var);
7535 %local i isin;
7536 %let n_vars=%sysfunc(countw(&vlist.));
7537 %let isin=0;
7538 %do i=1 %to &n_vars;
7539 %if &var.=%scan(&vlist.,&i) %then %do;
7540 %let isin=1;
7541 %end;
7542 %end;
7543
7544 &isin
7545 %mend;
7546
7547
7548
7549 %isin(&vrf_sellist., vrf_ordval_dif_acs_p); /*=1*/
MLOGIC(ISIN): Beginning execution.
MLOGIC(ISIN): Parameter VLIST has value vrf_ordval_dif_acs_p vrf_ordval_dif_mix_1
vrf_ordval_dif_mix_2 vrf_ordval_dif_p vrf_ordvol_dif_p vrf_ordvol_dif_p_d
vrf_val_dif_p
MLOGIC(ISIN): Parameter VAR has value vrf_ordval_dif_acs_p
MLOGIC(ISIN): %LOCAL I ISIN
MLOGIC(ISIN): %LET (variable name is N_VARS)
MLOGIC(ISIN): %LET (variable name is ISIN)
MLOGIC(ISIN): %DO loop beginning; index variable I; start value is 1; stop value is 7; by value is
1.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is TRUE
MLOGIC(ISIN): %LET (variable name is ISIN)
MLOGIC(ISIN): %DO loop index variable I is now 2; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 3; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 4; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 5; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 6; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 7; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 8; loop will not iterate again.
NOTE: Line generated by the macro variable "ISIN".
1 1
-
180
MPRINT(ISIN): 1
MLOGIC(ISIN): Ending execution.
ERROR 180-322: Statement is not valid or it is used out of proper order.
7550 %isin(&vrf_sellist., vrf_ordnet_dif_acs_p ); /*=0*/
MLOGIC(ISIN): Beginning execution.
MLOGIC(ISIN): Parameter VLIST has value vrf_ordval_dif_acs_p vrf_ordval_dif_mix_1
vrf_ordval_dif_mix_2 vrf_ordval_dif_p vrf_ordvol_dif_p vrf_ordvol_dif_p_d
vrf_val_dif_p
MLOGIC(ISIN): Parameter VAR has value vrf_ordnet_dif_acs_p
MLOGIC(ISIN): %LOCAL I ISIN
MLOGIC(ISIN): %LET (variable name is N_VARS)
MLOGIC(ISIN): %LET (variable name is ISIN)
MLOGIC(ISIN): %DO loop beginning; index variable I; start value is 1; stop value is 7; by value is
1.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 2; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 3; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 4; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 5; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 6; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 7; loop will iterate again.
MLOGIC(ISIN): %IF condition &var.=%scan(&vlist.,&i) is FALSE
MLOGIC(ISIN): %DO loop index variable I is now 8; loop will not iterate again.
NOTE: Line generated by the macro variable "ISIN".
1 0
-
180
MPRINT(ISIN): 0
MLOGIC(ISIN): Ending execution.
ERROR 180-322: Statement is not valid or it is used out of proper order.
Thank you
So, if you remove these two lines because they are unnecessary
%isin(&vrf_sellist., vrf_ordval_dif_acs_p); /*=1*/
%isin(&vrf_sellist., vrf_ordnet_dif_acs_p ); /*=0*/
and also replace %and with and
everything should work
First, thank you for showing us the entire LOG for this code. That's helpful. However, it would be 1,000 times better if you include the LOG in the window that appears when you click on the </> icon. This preserves the formatting of the LOG and makes it much easier to read. Please please please please please please please please please preserve the formatting of the LOG as described every time from now on.
It's not clear what your macro is supposed to be doing, or why you have this line in the code
&isin
but that is the error. This line creates SAS code, which SAS then tries to execute. But in SAS code, the number 0 by itself (or the number 1 by itself) is an error. I am thinking you did not intend it to be SAS code, so what is the intent here?
I am guessing that you want this macro variable &ISIN to be available to use after the macro runs. Is that correct? If so, remove that one line, remove ISIN from the %LOCAL command, and add this before you actually call the macro:
%global isin;
Use it as a logic ... isin is the return value
%let vrf_sellist=vrf_ordval_dif_acs_p vrf_ordval_dif_mix_1 vrf_ordval_dif_mix_2 vrf_ordval_dif_p vrf_ordvol_dif_p vrf_ordvol_dif_p_d vrf_val_dif_p; %macro isin(vlist, var); %local i isin; %let n_vars=%sysfunc(countw(&vlist.)); %let isin=0; %do i=1 %to &n_vars; %if &var.=%scan(&vlist.,&i) %then %do; %let isin=1; %end; %end; &isin %mend; %isin(&vrf_sellist., vrf_ordval_dif_acs_p); /*=1*/ %isin(&vrf_sellist., vrf_ordnet_dif_acs_p ); /*=0*/ %macro test(); %if %isin(&vrf_sellist., var)=1 %and %isin(&vrf_sellist., vrf_ordval_dif_acs_p)=1 %then %do; %put "both match"; %end; %else %do; %put "has non-match"; %end; %mend; %test();
Please post code in the code box. Click on the "little running man" icon and paste your code into the box that appears.
%let vrf_sellist=vrf_ordval_dif_acs_p vrf_ordval_dif_mix_1 vrf_ordval_dif_mix_2 vrf_ordval_dif_p vrf_ordvol_dif_p vrf_ordvol_dif_p_d vrf_val_dif_p; %macro isin(vlist, var); %local i isin; %let n_vars=%sysfunc(countw(&vlist.)); %let isin=0; %do i=1 %to &n_vars; %if %scan(&var.,1)=%scan(&vlist.,&i) %then %do; %let isin=1; %end; %end; &isin %mend; %isin(&vrf_sellist., vrf_ordval_dif_acs_p); /*=1*/ %isin(&vrf_sellist., vrf_ordnet_dif_acs_p ); /*=0*/ %macro test(); %if %isin(&vrf_sellist., var)=1 %and %isin(&vrf_sellist., vrf_ordval_dif_acs_p)=1 %then %do; %put "both match"; %end; %else %do; %put "has non-match"; %end; %mend; %test();
Thank you
So, if you remove these two lines because they are unnecessary
%isin(&vrf_sellist., vrf_ordval_dif_acs_p); /*=1*/
%isin(&vrf_sellist., vrf_ordnet_dif_acs_p ); /*=0*/
and also replace %and with and
everything should work
You may also want to use the %inm macro, which is the equivalent of the non-macro IN function
%macro inm(slist,s);
/* SAS Macro %inm to see if &s is contained in a string or list &slist */
/* Borrowed from https://groups.google.com/forum/#!topic/comp.soft-sys.sas/fWcSDgg11tE */
%if %sysfunc(indexw(&slist,&s)) gt 0 %then 1 ;
%else 0;
%mend;
The macro itself looks OK, but the way you are calling it is not what it is intended for. Let's assume you remove the semicolon at the end of the macro call, so you have:
%isin(&vrf_sellist., vrf_ordval_dif_acs_p)
This macro call is intended to return a 1 or a 0. So you have to use it in a place where your program would expect to process a 1 or a 0. For example:
%if %isin(&vrf_sellist., vrf_ordval_dif_acs_p) %then %do;
Know what you say. The quest is when with extra space, the return value changes from 1 to 0.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.