BookmarkSubscribeRSS Feed
BrianDiamante
Calcite | Level 5
I have a macro which uses a %DO statement to run a datastep four times. Each time, I set the variable "var" equal to the value contained in the array "letters" at the index of &i. I then use this datastep variable "var" as the condition for my %IF-%THEN-%ELSE statement. See below:


%macro test2;

data c1;
a='a';
b='b';
c='';
d='d';
run;

%do iterator = 1 %to 4;
data c2;
set c1;
array letters (4) $25 a b c d;
x=&iterator;
var=strip(letters);
put +5 "Iteration Number:" x +3 "var=" var;

%if var = 'b' %then %do;
put "WARNING-" +4 "The macro condition was true!!!";
put;
%end;
%else %do;
put "ERROR-" +4 "The macro condition was false!!!";
put;
%end;

run;

%end;
%mend;

%test2;



The problem I am having is that the %if statement always evaluates the same (either true or false) for all 4 iterations of the datastep c2. My output is below:



MLOGIC(TEST2): Beginning execution.
MPRINT(TEST2): data c1;
MPRINT(TEST2): a='a';
MPRINT(TEST2): b='b';
MPRINT(TEST2): c='';
MPRINT(TEST2): d='d';
MPRINT(TEST2): run;

NOTE: The data set WORK.C1 has 1 observations and 4 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds


MLOGIC(TEST2): %DO loop beginning; index variable ITERATOR; start value is 1; stop value is 4; by value
is 1.
MPRINT(TEST2): data c2;
MPRINT(TEST2): set c1;
MPRINT(TEST2): array letters (4) $25 a b c d;
SYMBOLGEN: Macro variable ITERATOR resolves to 1
MPRINT(TEST2): x=1;
MPRINT(TEST2): var=strip(letters);
MPRINT(TEST2): put +5 "Iteration Number:" x +3 "var=" var;
MLOGIC(TEST2): %IF condition var = 'b' is FALSE
MPRINT(TEST2): put "ERROR-" +4 "The macro condition was false!!!";
MPRINT(TEST2): put;
MPRINT(TEST2): run;

Iteration Number:1 var=a
The macro condition was false!!!

NOTE: There were 1 observations read from the data set WORK.C1.
NOTE: The data set WORK.C2 has 1 observations and 6 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds


MLOGIC(TEST2): %DO loop index variable ITERATOR is now 2; loop will iterate again.
MPRINT(TEST2): data c2;
MPRINT(TEST2): set c1;
MPRINT(TEST2): array letters (4) $25 a b c d;
SYMBOLGEN: Macro variable ITERATOR resolves to 2
MPRINT(TEST2): x=2;
MPRINT(TEST2): var=strip(letters);
MPRINT(TEST2): put +5 "Iteration Number:" x +3 "var=" var;
MLOGIC(TEST2): %IF condition var = 'b' is FALSE
MPRINT(TEST2): put "ERROR-" +4 "The macro condition was false!!!";
MPRINT(TEST2): put;
MPRINT(TEST2): run;

Iteration Number:2 var=b
The macro condition was false!!!

NOTE: There were 1 observations read from the data set WORK.C1.
NOTE: The data set WORK.C2 has 1 observations and 6 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds


MLOGIC(TEST2): %DO loop index variable ITERATOR is now 3; loop will iterate again.
MPRINT(TEST2): data c2;
MPRINT(TEST2): set c1;
MPRINT(TEST2): array letters (4) $25 a b c d;
SYMBOLGEN: Macro variable ITERATOR resolves to 3
MPRINT(TEST2): x=3;
MPRINT(TEST2): var=strip(letters);
MPRINT(TEST2): put +5 "Iteration Number:" x +3 "var=" var;
MLOGIC(TEST2): %IF condition var = 'b' is FALSE
MPRINT(TEST2): put "ERROR-" +4 "The macro condition was false!!!";
MPRINT(TEST2): put;
MPRINT(TEST2): run;

Iteration Number:3 var=
The macro condition was false!!!

NOTE: There were 1 observations read from the data set WORK.C1.
NOTE: The data set WORK.C2 has 1 observations and 6 variables.
NOTE: DATA statement used (Total process time):
real time 0.07 seconds
cpu time 0.01 seconds


MLOGIC(TEST2): %DO loop index variable ITERATOR is now 4; loop will iterate again.
MPRINT(TEST2): data c2;
MPRINT(TEST2): set c1;
MPRINT(TEST2): array letters (4) $25 a b c d;
SYMBOLGEN: Macro variable ITERATOR resolves to 4
MPRINT(TEST2): x=4;
MPRINT(TEST2): var=strip(letters);
MPRINT(TEST2): put +5 "Iteration Number:" x +3 "var=" var;
MLOGIC(TEST2): %IF condition var = 'b' is FALSE
MPRINT(TEST2): put "ERROR-" +4 "The macro condition was false!!!";
MPRINT(TEST2): put;
MPRINT(TEST2): run;

Iteration Number:4 var=d
The macro condition was false!!!

NOTE: There were 1 observations read from the data set WORK.C1.
NOTE: The data set WORK.C2 has 1 observations and 6 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds


MLOGIC(TEST2): %DO loop index variable ITERATOR is now 5; loop will not iterate again.
MLOGIC(TEST2): Ending execution.


As you can see from the log output, the %IF condition fails in all four iterations.. however I had expected it to be true for the second iteration as var=b during the second iteration. Can anyone shed some light here on what is really going on and where my misunderstanding might be?


Thanks,
Brian
5 REPLIES 5
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
The SAS program you posted appears to be mixing DATA step logic and MACRO code logic, which is not supported. You can see from the SAS-generated MLOGIC log messages that any attempt to reference a SAS DATA step variable from a MACRO language statement will not work - the string is treated as character data.

When attempting to use the MACRO LANGUAGE, it's best to get a working program defined and tested -- then determine how, if at all, you may see the MACRO language helping with your particular SAS environment / operational processing requirements.

Scott Barry
SBBWorks, Inc.
BrianDiamante
Calcite | Level 5
So the condition for %IF must reference a macro variable only?

Brian
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
Normally, yes - do consider that SAS macro language code elements are executed at SAS program compilation time, unlike DATA step language elements which are executed with each DATA step iteration.

Scott Barry
SBBWorks, Inc.

Suggested Google advanced search argument, this topic / post:

macro language site:sas.com

macro read sas file sysfunc site:sas.com
Cynthia_sas
SAS Super FREQ
And, in addition to Scott's suggestions, this paper provides a good introduction to macro processing concepts and Step 9 shows how to use %IF to conditionally execute whole program steps or conditionally insert selected statements into compiled code:
http://www2.sas.com/proceedings/sugi28/056-28.pdf

cynthia
chang_y_chung_hotmail_com
Obsidian | Level 7
I find it helpful separating out the iteration mechanism and the task that is to get done for each iteration.



   /* input data */


   data c1;


      a='a';


      b='b';


      c='';


      d='d';   


   run;


 


   /* macro to iterate */


   %macro doSomething(iter=);


      data c2;


         set c1;


         array letters(4) $ a b c d;


         x = &iter;


         var = strip(letters(x));


         if var='b' then put x= "true. var='b'";


         else put x= "false. var^='b'";


      run;


   %mend  doSomething;


 


   %*-- test running it one at a time --*;


   %doSomething(iter=1)


   %doSomething(iter=2)


 


   %*-- run them all --*;


   %macro doAll;


      %local i;


      %do i = 1 %to 4;


         %doSomething(iter=&i)


      %end;


   %mend  doAll;


   %doAll


   %*-- on log


   x=1 false. var^='b'


   x=2 true. var='b'


   x=3 false. var^='b'


   x=4 false. var^='b'


   --*;

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 5 replies
  • 1153 views
  • 0 likes
  • 4 in conversation