BookmarkSubscribeRSS Feed
SASMom2
Fluorite | Level 6

I need to write a condition macro using %if - %else. Below is an example. 

I am creating ‘typ’ macro to create a table depending on the values of ‘cust’. If the values are ‘abc’ or ‘def’ then I want to run one set of proc sql else run another set of proc sql.

%macro Typ;

  %if "&cust." = "abc" or %if "&cust." = "def" %then %do;

      proc sql;

      quit;

%end;

%else %do;

      proc sql;

      quit;

%end;

%mend Typ;

%Typ;

 ***********************************************************

 I tried below %if statements.

 

1)  %if "&cust." = "abc" or %if "&cust." = "def" %then %do;

2)  %if "&cust." in ("abc","def"%then %do;

 

When I run the code for cust = def using the 1st %if statement above the log says “&cust.” = “def” is FALSE so it goes to the else part and runs the second set of proc sql. When ran the code using the 2nd %if statement, it does not recognize ‘in’ as an operator.

 

3) %if "&cust." = 'abc' or %if "&cust." = 'def' %then %do; / *single quotes */

4)  %if "&cust." in ('abc','def'%then %do/* single quotes */

 

I tried to run same 1st and 2nd %if statements using single quotes (statements 3 and 4 above) for the ‘cust’ values, it gave error.

 Please help.

Thanks

8 REPLIES 8
PaigeMiller
Diamond | Level 26

Generally, you don't use quotes around text or quotes around macro variables in macro language. You want

 

%if &cust. = abc or &cust. = def %then %do;

 

 

Also, the second %IF in your original code is wrong, that's not proper syntax if you want to test two conditions; and so the above syntax that I have provided with just one %IF should work.

 

Also, you don't show how &cust is assigned a value, there should not be quotes in most cases around the value of &cust.

--
Paige Miller
Quentin
Super User

You've got good answers from others.  But just to add, when you compile a macro, it's important to make sure the macro compiles successfully.  When I submit your code, there is a macro compilation error reported in the log, because of the extra %IF you have after the OR:

 

1    %macro Typ;
2
3      %if "&cust." = "abc" or %if "&cust." = "def" %then %do;
ERROR: Macro keyword IF appears as text.
ERROR: A dummy macro will be compiled.
4
5          proc sql;
6
7          quit;
8
9    %end;
10
11   %else %do;
12
13         proc sql;
14
15         quit;
16
17   %end;

If you turn on the option MCOMPILENOTE, you will get a confirmation NOTE when a macro is compiled:

83   options mcompilenote=all ;
84   %macro Typ(cust=);
85     %if &cust = abc or &cust = def %then %do;
86       proc sql;
87       quit;
88     %end;
89     %else %do;
90       proc sql;
91       quit;
92     %end;
93   %mend Typ;
NOTE: The macro TYP completed compilation without errors.
      18 instructions 364 bytes.

 

BASUG is hosting free webinars Next up: Mark Keintz presenting History Carried Forward, Future Carried Back: Mixing Time Series of Differing Frequencies on May 8. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
AMSAS
SAS Super FREQ

Run this example code and review the SAS log

options mprint mlogic symbolgen ;

%macro typ(cust=) ;
	%if &cust=abc or &cust=def %then 
	%do ;
		%PUT *** TRUE  - Cust is &cust *** ;
	%end ;
	%else %do ;
		%PUT *** FALSE - Cust is &cust *** ;
	%end ;
%mend typ ;

%typ(cust=abc) ;
%typ(cust=def) ;
%typ(cust=DEF) ;
%typ(cust=ghi) ;

SAS log, in spoiler 

Spoiler
815  options mprint mlogic symbolgen ;
816
817  %macro typ(cust=) ;
818      %if &cust=abc or &cust=def %then
819      %do ;
820          %PUT *** TRUE  - Cust is &cust *** ;
821      %end ;
822      %else %do ;
823          %PUT *** FALSE - Cust is &cust *** ;
824      %end ;
825  %mend typ ;
826
827  %typ(cust=abc) ;
MLOGIC(TYP):  Beginning execution.
MLOGIC(TYP):  Parameter CUST has value abc
SYMBOLGEN:  Macro variable CUST resolves to abc
SYMBOLGEN:  Macro variable CUST resolves to abc
MLOGIC(TYP):  %IF condition &cust=abc or &cust=def is TRUE
MLOGIC(TYP):  %PUT *** TRUE  - Cust is &cust ***
SYMBOLGEN:  Macro variable CUST resolves to abc
*** TRUE  - Cust is abc ***
MLOGIC(TYP):  Ending execution.
828  %typ(cust=def) ;
MLOGIC(TYP):  Beginning execution.
MLOGIC(TYP):  Parameter CUST has value def
SYMBOLGEN:  Macro variable CUST resolves to def
SYMBOLGEN:  Macro variable CUST resolves to def
MLOGIC(TYP):  %IF condition &cust=abc or &cust=def is TRUE
MLOGIC(TYP):  %PUT *** TRUE  - Cust is &cust ***
SYMBOLGEN:  Macro variable CUST resolves to def
*** TRUE  - Cust is def ***
MLOGIC(TYP):  Ending execution.
829  %typ(cust=DEF) ;
MLOGIC(TYP):  Beginning execution.
MLOGIC(TYP):  Parameter CUST has value DEF
SYMBOLGEN:  Macro variable CUST resolves to DEF
SYMBOLGEN:  Macro variable CUST resolves to DEF
MLOGIC(TYP):  %IF condition &cust=abc or &cust=def is FALSE
MLOGIC(TYP):  %PUT *** FALSE - Cust is &cust ***
SYMBOLGEN:  Macro variable CUST resolves to DEF
*** FALSE - Cust is DEF ***
MLOGIC(TYP):  Ending execution.
830  %typ(cust=ghi) ;
MLOGIC(TYP):  Beginning execution.
MLOGIC(TYP):  Parameter CUST has value ghi
SYMBOLGEN:  Macro variable CUST resolves to ghi
SYMBOLGEN:  Macro variable CUST resolves to ghi
MLOGIC(TYP):  %IF condition &cust=abc or &cust=def is FALSE
MLOGIC(TYP):  %PUT *** FALSE - Cust is &cust ***
SYMBOLGEN:  Macro variable CUST resolves to ghi
*** FALSE - Cust is ghi ***
MLOGIC(TYP):  Ending execution.
Tom
Super User Tom
Super User

 1)  %if "&cust." = "abc" or %if "&cust." = "def" %then %do;

So that is invalid syntax.  The syntax for a %IF statement is %IF ... %THEN ... ;  You cannot have %IF ... %IF ... since there is no %THEN for the first %IF.

 

Instead use:

%if "&cust." = "abc" or  "&cust." = "def" %then %do;

And for this second syntax to work:

2)  %if "&cust." in ("abc","def") %then %do;

You have to have told SAS to allow the use of IN as an operator in the macro language by setting the MINOPERATOR option on.  You also need to have set the MINDELIMITER option to ',' so that it knows that you want to use a comma as the list delimiter.  The parentheses are not needed, but do no harm.

 

Since the code is inside of a macro the best way is to add those options to the %MACRO statement so that it will work no matter what values the caller has set for those options.

%macro Typ / minoperator mindelimiter=',' ;

 

And the last two

3) %if "&cust." = 'abc' or %if "&cust." = 'def' %then %do; / *single quotes */

4)  %if "&cust." in ('abc','def'%then %do/* single quotes */

(3) has the same problem as (1).  And they both can never be true because a single quote is different character than a double quote.  So no matter what the content of the CUST macro variable the string on the left will never equal the string(s) on the right.

 

 

ErikLund_Jensen
Rhodochrosite | Level 12

Hi @SASMom2 

As noticed by @PaigeMiller , your first statement is syntactically wrong, because you cannot combine two %if conditions with an OR-operator.

 

You don't need the double quotes, because they are not acting as quotes in the macro language. They are treated as text and becomes part of the value. So when used on both sides in the equation,the result will be the same.

 

You can use the trailing . after a macro variable name, but it not necessary. It acts as a delimiter between a macro variable name and something immediately following it, so this something is not seen as part of the macro variable name.

 

As for your second statement, you can also use the in operator in macro language, but you need a MINOPERATOR option to tell the macro compiler that it should accept it. So these four macros all work and give the same result:

 

%macro typ(cust=);
	%if "&cust"="abc" or "&cust"="def" %then %put TRUE  - Cust is &cust;
	%else %put FALSE - Cust is &cust;
%mend;

%macro typ(cust=);
	%if &cust=abc or &cust=def %then %put TRUE  - Cust is &cust;
	%else %put FALSE - Cust is &cust;
%mend;

%macro typ(cust=) / minoperator;
	%if "&cust." in ("abc" "def") %then %put TRUE  - Cust is &cust;
	%else %put FALSE - Cust is &cust;
%mend;

%macro typ(cust=) / minoperator;
	%if &cust. in (abc def) %then %put TRUE  - Cust is &cust;
	%else %put FALSE - Cust is &cust;
%mend;

%typ(cust=abc) ;
%typ(cust=def) ;
%typ(cust=DEF) ;
%typ(cust=ghi) ;

 

SASMom2
Fluorite | Level 6

Thank you everyone for your reply. Below statement worked.

  %if  &cust. = 'abc' or &cust. = 'def' %then %do;

 

Tom
Super User Tom
Super User

@SASMom2 wrote:

Thank you everyone for your reply. Below statement worked.

  %if  &cust. = 'abc' or &cust. = 'def' %then %do;

 


Only if you remember to include the quotes in the value you pass to the macro.

%typ(cust='abc')
PaigeMiller
Diamond | Level 26

@SASMom2 wrote:

Thank you everyone for your reply. Below statement worked.

  %if  &cust. = 'abc' or &cust. = 'def' %then %do;

 


And yet there is almost never a good reason to have quotes around abc or def in the above example.

 

%let cust=abc;

 

and then later

 

 

%if  &cust. = abc or &cust. = def %then %do;

 

 

The idea of typing quotes around macro constants makes me cringe. As stated, it is unnecessary, it is extra typing (and I find typing quotes to be particularly prone to making errors), and it means you have an improper understanding of macro variables. The understanding you need is that macro variables are always text (even if they look like numbers, they are text), this is understood by the macro processor and so unlike data steps, you don't have to put values in quotes because the macro processor knows the values are text.

--
Paige Miller

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
  • 8 replies
  • 473 views
  • 2 likes
  • 6 in conversation