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

Post has been considerably edited (Sorry for this).


I run this pseudo program: 

 

%macro myfun(country); 
	%let country = %sysfunc(upcase(&country)); *Making the macro case insensitve;

	%if &country. = FI or US or GB or SW or DK %then %do;  
		%put ERROR: Country in the list;
	%end;
	%else %do;
		%put Error: Just some random text; 
	%end;
%mend myfun; 

%myfun(FI); 

It returns the error: 

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 
       &country. = FI or US or GB or SW or DK 
ERROR: The macro MYFUN will stop executing.

Any advice?

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Use the IN operator, not the equality operator, to test if value is in a list.  To use the IN operator make sure to set the MINOPERATOR and MINDELIMITER options on the %MACRO statement.  Otherwise your macro will perform differently based on what users have set those options to in the calling program.

 

Do not use datastep functions via %SYSFUNC() when there is already a macro function for that operation.

 

Add macro quoting in case the values passed have strange characters that will impact the testing of the values.

%macro myfun(country) / minoperator mindelimiter=' '; 
	%let country = %qupcase(&country); 
	%if &country. in FI US GB SW DK %then %do;  
		%put NOTE: &=country is in the list;
	%end;
	%else %do;
		%put ERROR: &=country is not in the list; 
	%end;
%mend myfun; 
24    %myfun(FI)
NOTE: COUNTRY=FI is in the list
25    %myfun(us)
NOTE: COUNTRY=US is in the list
26    %myfun(usa)
ERROR: COUNTRY=USA is not in the list

View solution in original post

13 REPLIES 13
PaigeMiller
Diamond | Level 26

When I run your code, I get a different error.

 

254   %macro myfun(country);
255       %let country = %sysfunc(upcase(&random)); *Making the macro case insensitve;
256
257       %if &country. ^= FI US GB SW DK %then %do;
258           %put ERROR: Country not in the list
259       %end;
ERROR: Macro keyword END appears as text.
ERROR: A dummy macro will be compiled.
260   %mend myfun;
261
262   %myfun(E);

You might want to consider using %upcase instead of %sysfunc(upcase()). You might also want to consider defining variable &RANDOM before you use it. Hint hint hint.

 

Next, macro processor will test your &COUNTRY macro variable to see if it is (or is not) equal to the text string FI US GB SW DK and there is no such country, every country name or abbreviation in the world is not equal to the text string FI US GB SW DK so you really need to think this through carefully.

--
Paige Miller
SasStatistics
Pyrite | Level 9

restarted my SAS and got something else, I edited my post considerably. 

PaigeMiller
Diamond | Level 26

Why would SAS not recognize the %END; command???? Look very very carefully. 


Also, a second problem after that is that you haven't grasped my point about comparing &COUNTRY to the text string shown.

--
Paige Miller
japelin
Rhodochrosite | Level 12

Missing semicolon at the end of %put statement

 

so, fix this

%put ERROR: Country not in the list

to

%put ERROR: Country not in the list;

 

SasStatistics
Pyrite | Level 9
Edited my post considerably (please see the new version), thanks for the reply.
japelin
Rhodochrosite | Level 12

If the problem has been solved, mark the thread as solved and close it.

Then you should post a new question.

Otherwise, the exchange in the middle will be meaningless (in hindsight).

PaigeMiller
Diamond | Level 26

The problem is that the macro processor considers the stuff on the right hand side of the equal sign to be text. It doesn't know that you want to LOOP through each value shown there and do the test and then see if &COUNTRY matches one of the five abbreviations. Macros don't loop, unless you specifically tell it to do so, which you have not done.

 

You can also use native macro commands to determine if &country is IN the list 

FI US GB SW DK

but there are some reasons why people don't like to do that and I won't get into this.

 

I like to use the %inm macro to do things like this. Here is how I would do it:

 

%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;

%macro myfun(country); 
	%let country = %sysfunc(upcase(&country));
	%if not %inm(FI US GB SW DK,&country) %then %do;  
		%put ERROR: Country not in the list;
	%end;
	%else %do;
		%put Country &country found; 
	%end;
%mend myfun; 

%myfun(FI)

If you don't want to do it that way, the proper syntax is

 

%if &country = FI or &country = US or &country = GB or &country = SW or &country = DK %then %do;  

 

--
Paige Miller
japelin
Rhodochrosite | Level 12

try this

options minoperator mindelimiter=',';
%macro myfun(country); 
	%let country = %sysfunc(upcase(&country)); *Making the macro case insensitve;

	%if &country. in (FI, US, GB, SW, DK) %then %do;  
		%put ERROR: Country in the list;
	%end;
	%else %do;
		%put Error: Just some random text; 
	%end;
%mend myfun; 

%myfun(FI); 
Kurt_Bremser
Super User

This condition

%if &country. = FI or US or GB or SW or DK

evaluates to this condition

%if (&country. = FI) or (US) or (GB) or (SW) or (DK)

Since none of

US GB SW DK

are valid boolean values (numeric, missing or 0 = false, any other = true), this must fail.

SasStatistics
Pyrite | Level 9
Now in hindsight, this makes alot of sense.

Any advice on how I could come up with this "myself"?
PaigeMiller
Diamond | Level 26

How about this: https://communities.sas.com/t5/SAS-Programming/Free-Webinar-How-Do-I-Build-a-Macro-Application/m-p/7...

 

There are plenty of tutorials on macros, and SAS maintains an extensive YouTube channel, I'm sure you can find macro information there.

--
Paige Miller
Tom
Super User Tom
Super User

The difference between in operation and equality operator is basic understanding of logical expressions.  So general programming knowledge will help.

 

To find what operators SAS supports check the documentation.

Macro language operators

or

General SAS operators 

Tom
Super User Tom
Super User

Use the IN operator, not the equality operator, to test if value is in a list.  To use the IN operator make sure to set the MINOPERATOR and MINDELIMITER options on the %MACRO statement.  Otherwise your macro will perform differently based on what users have set those options to in the calling program.

 

Do not use datastep functions via %SYSFUNC() when there is already a macro function for that operation.

 

Add macro quoting in case the values passed have strange characters that will impact the testing of the values.

%macro myfun(country) / minoperator mindelimiter=' '; 
	%let country = %qupcase(&country); 
	%if &country. in FI US GB SW DK %then %do;  
		%put NOTE: &=country is in the list;
	%end;
	%else %do;
		%put ERROR: &=country is not in the list; 
	%end;
%mend myfun; 
24    %myfun(FI)
NOTE: COUNTRY=FI is in the list
25    %myfun(us)
NOTE: COUNTRY=US is in the list
26    %myfun(usa)
ERROR: COUNTRY=USA is not in the list

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 13 replies
  • 2664 views
  • 8 likes
  • 5 in conversation