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

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
Shmuel
Garnet | Level 18

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)

 

View solution in original post

11 REPLIES 11
Shmuel
Garnet | Level 18

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
Quartz | Level 8
I am getting this error
"ERROR: Required operator not found in expression: INDEX('ABC_test.xlsx','ABC')
SASAna
Quartz | Level 8
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
Kurt_Bremser
Super User

@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.

ballardw
Super User

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

Kurt_Bremser
Super User

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;
RW9
Diamond | Level 26 RW9
Diamond | Level 26

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.

SASAna
Quartz | Level 8

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.

 

Shmuel
Garnet | Level 18

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)

 

SASAna
Quartz | Level 8
Worked perfect 🙂 I added a macro for all the true conditions to continue my SAS analysis.

Thank you .
Ana

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 11 replies
  • 7365 views
  • 1 like
  • 5 in conversation