I am writing a macro and trying to find the string using INDEX function from a parameter that is being passed in the macro.
if FILENAME is 'FILENAME_ABC' , FIND_ABC is resolving it to 1 but if condition is telling true for all the conditions and name & Lastname is showing wrong.
%MACRO XYZ(FILENAME);
%LET FIND_ABC = INDEX(&FILENAME,'ABC') ;
%IF FIND_ABC > 0 %THEN %DO;
%LET NAME= 'ABC' ;
%LET LASTname = 'XYZ';
%LET FIND_MNB = INDEX(&FILENAME,'MNB') ;
%IF FIND_MNB > 0 %THEN %DO;
%LET NAME= 'MNB' ;
%LET LASTname = 'TRY';
%END;
%MEND(FILENAME);
Thanks,
Ana
In a macro program you do not need to quote the strings (I missed it in my previous post);
You also missed some syntax defining and using a macro program.
%MACRO XYZ(FILENAME);
%LET FIND_ABC = %INDEX(&FILENAME,ABC) ;
%IF %eval(&FIND_ABC) > 0 %THEN %DO;
%LET NAME= ABC ;
%LET LASTname = XYZ;
%END;
%PUT (1) name=&name lastname=&lastname;
%LET FIND_MNB = %INDEX(&FILENAME,MNB) ;
%IF %eval(&FIND_MNB ) > 0 %THEN %DO;
%LET NAME= MNB;
%LET LASTname = TRY;
%END;
%PUT (2) name=&name lastname=&lastname;
%MEND XYZ;
%XYZ(FILENAME);
%PUT (3) name=&name lastname=&lastname;
Using same macro variables names twice will end by the last only.
How do you want to refer the macro variables later ? -
Log message (3) equals to (2), and you miss the (1)
you have a mismatch of macro programming with data step programming..
Your code with slight changes should work:
%MACRO XYZ(FILENAME);
%LET FIND_ABC = %INDEX(&FILENAME,'ABC') ;
%IF %eval(&FIND_ABC) > 0 %THEN %DO;
%LET NAME= 'ABC' ;
%LET LASTname = 'XYZ';
%END;
%LET FIND_MNB = %INDEX(&FILENAME,'MNB') ;
%IF %eval(&FIND_MNB ) > 0 %THEN %DO;
%LET NAME= 'MNB' ;
%LET LASTname = 'TRY';
%END;
%MEND(FILENAME);
%PUT name=&name lastname=&lastname;
@SASAna wrote:
Sorry, error was different .
SYMBOLGEN: Macro variable FIND_ABC resolves to 0
MLOGIC(XYZ): %IF condition %eval(&FIND_ABC) > 0 is FALSE
MLOGIC(XYZ): %PUT NAME=&NAME
WARNING: Apparent symbolic reference NAME not resolved.
NAME=&NAME
You also need to show the code that is supposed to set the macro variable name, as the error is most probably there.
Post the complete step code & log; because this works:
16 data _null_; 17 x1 = INDEX('ABC_test.xlsx','ABC'); 18 put x1=; 19 run; x1=1
These lines of code
%IF FIND_ABC > 0 %THEN %DO;
FIND_MNB > 0
are comparing the actual text FIND_ABC to 0 since F is "greater than 0" (follows 0 in the sort sequence0 the result is true or 1.
If you want to compare the VALUE of the macro variable then you want to use & to tell the processor to use the macro variable
%IF &FIND_ABC > 0 %THEN %DO;
Hover FIND_abc has the value of "Index(&filename,'ABC')", not 1 or something else. If you want Find_ABC to have the position of ABC in the value &filename then you want to use the MACRO fuction %index not the datastep function Index.
So
%LET FIND_ABC = INDEX(&FILENAME,'ABC') ;
%IF &FIND_ABC > 0 %THEN %DO;
You are also likely missing and %end statement for the %if &find_abc
You cannot use data step functions in macro language without wrapping them in %sysfunc, so
%xyz(xxx);
would execute this
%LET FIND_ABC = INDEX(xxx,'ABC') ;
If you used
%put "&find_abc";
you would get
"INDEX(xxx,'ABC')"
in the log.
Next, you omitted the ampersand to address macro variables, so
%IF FIND_ABC > 0
compares the text "FIND_ABC" with the text "0", which is always true.
Keep in mind: the macro processor is a pure text processor, intended mostly to create dynamic program text.
If you want to manipulate strings, do so in a data step, and save the results to macro variables with call symput if needed:
%macro xyz(filename);
%global name lastname;
data _null_;
if index("&filename",'ABC') > 0
then do;
call symput('name','ABC');
call symput('lastname','XYZ');
end;
if index("&filename",'MNB') > 0
then do;
call symput('name','MNB');
call symput('lastname','TRY');
end;
run;
%mend;
Why do you need to do it in a macro? Macro language Only creates Base SAS code, so why not use Base SAS in the first place? Also, please avoid coding all in upper case, it makes reading the code sound like your shouting it at me.
I need to do this code in macro as i have to refer them at different part of the code to update the tables.
%LET FIND_MATH = %INDEX(&FILENAME,'MATH') ;
%IF %eval(&FIND_MATH) > 0 %THEN %DO;
%LET TEXT = 'MATHS' ;
%LET MyTable = MATH_TABLE;
%END;
%LET FIND_SCIENCE = %INDEX(&FILENAME,'SCIENCE');
%IF %eval(&FIND_SCIENCE) > 0 %THEN %DO;
%LET TEXT = 'SCIENCE';
%LET MyTable = SCIENCE_TABLE;
%END;
%LET FIND_GEOGRAPHY = %INDEX(&FILENAME,"GEOGRAPHY");
%IF %eval(&FIND_GEOGRAPHY) > 0 %THEN %DO;
%LET TEXT = 'GEOGRAPHY';
%LET MyTable = GEOGRAPHY_TABLE;
%END;
ETC ( ALL THE SUBJECTS SHOULD BE SERACHED & i HAVE TO GO TO THE TABLE TO UPDATE IT AT LATER POINT OF THE CODE)
ERROR -
I am passing MATH_TEXT.xlsx as FILENAME in the macro
MLOGIC(TEXT_BOOKS): %IF condition %eval(&FIND_MATH) > 0 is FALSE
MLOGIC(TEXT_BOOKS): %PUT TEXT=&TEXT
WARNING: Apparent symbolic reference TEXT not resolved.
In a macro program you do not need to quote the strings (I missed it in my previous post);
You also missed some syntax defining and using a macro program.
%MACRO XYZ(FILENAME);
%LET FIND_ABC = %INDEX(&FILENAME,ABC) ;
%IF %eval(&FIND_ABC) > 0 %THEN %DO;
%LET NAME= ABC ;
%LET LASTname = XYZ;
%END;
%PUT (1) name=&name lastname=&lastname;
%LET FIND_MNB = %INDEX(&FILENAME,MNB) ;
%IF %eval(&FIND_MNB ) > 0 %THEN %DO;
%LET NAME= MNB;
%LET LASTname = TRY;
%END;
%PUT (2) name=&name lastname=&lastname;
%MEND XYZ;
%XYZ(FILENAME);
%PUT (3) name=&name lastname=&lastname;
Using same macro variables names twice will end by the last only.
How do you want to refer the macro variables later ? -
Log message (3) equals to (2), and you miss the (1)
Available on demand!
Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.
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.