0
votes

I have inherited macro in which the below block does not seem to be resolved. The macro is supposed to conditionally select the logical operations based on the date values. If the %if conditions are satisfied, they should print the macro variables mentioned in the %put statement, which in-turn become part of the if condition. If the condition %if %length(&datein.)=10 OR %length(ST_&date.)=10 is satisfied, it would print the first %put statement else the second %put statement would be printed. Same logic applies to the second %if statement.

The macro is supposed to be run inside a data step. The logical operator AND is being considered as a variable and I'm getting a note NOTE: Variable AND is uninitialized.

I tried to balance the if condition by adding the open and closed parenthesis mentioned in below code. Tried to change the structure of the if condition to separate the first and the second condition, but doesn't seem to work. I assuming that the logical operator AND cannot be used as it is in the %if %then %else statement.

%macro test_date(date=, comp1=, comp2=, label=);
            if &datein. ne "" and ST_&date. ne "" then do;
                if (%if %length(&datein.)=10 OR %length(ST_&date.)=10 %then %put ST_&date._10 &comp1. datein_10; %else %put ST_&date._19 &comp1. datein_19;
                AND %if %length(&datein.)=10 OR %length(ED_&date.)=10 %then %put datein_10 &comp2. ED_&date._10; %else %put datein_19 &comp2. ED_&date._19;)
                then EPOCH=&label.;
            end;
%mend test_date;

%test_date(date=SCREEN, comp1= le, comp2= le, label='SCREEN');
2
It doesn't make much sense to me. It is if, then, else and epoch (instead of %if, %then, %else and %let epoch), so i assume it is supposed to run in a data step? The stuff in the inner if writes to the log and will not resolve to true or false when the data step runs. And can't be first in a statement. ST_&date seems to be data step variable in the outer if and a string in the inner one. What is this supposed to do? - RuneS
Apologies for not making it clear. I have updated my question. - Nimit_ZZ
What do you expect the macro to do? What SAS code do you want the macro to generate? - Tom
Show the rest of the data step that you are trying to use this macro to generate part of. - Tom
If the %if conditions are satisfied, they should print the macro variables mentioned in the %put statement, which in-turn become part of the if condition. This code snippet is part of a huge code which would be tedious. - Nimit_ZZ

2 Answers

1
votes

You will probably need to adapt this a bit, but it should be helpful in clearifying the logic of it. The code below checks the length of macro variables and inserts data step code based on this length. It will also print some values to the log, but that doesn't affect results. I've included some simple data step examples to illustrate how it works.

%macro test_date(date=, comp1=, comp2=, label=);
    %if &datein. ne  and &&ST_&date. ne  %then %do;

        %if %length(&datein.)=10 OR %length(&&ST_&date.)=10 %then %do;
            /*  Insert data step code */
            if variable1=1 then epoch="First condition";
            else epoch="firstelse";
            /*  Print to log*/
            %put &&ST_&date. &comp1. &datein.; 
        %end;
        %else %if %length(&datein.)=10 OR %length(&&ED_&date.)=10 %then %do;
            if variable1=0 then epoch="Second condition";
            else epoch="secondelse";
        %end;

    %end;
%mend test_date;

/*  Macro variables given values of length 10. Outer if and first condition in do block holds.*/
%let datein=0123456789;
%let st_screen=0123456789;
%let ed_screen=0123456789;

data test1;
    variable1=1;
    %test_date(date=SCREEN, comp1= le, comp2= le, label='SCREEN');
run;


data test2;
    variable1=0;
    %test_date(date=SCREEN, comp1= le, comp2= le, label='SCREEN');
run;

/*  Macro variables given values of length 9 and 10. Outer if and else condition in do block holds.*/
%let datein=012345678;
%let st_screen=012345678;
%let ed_screen=0123456789;


data test3;
    variable1=1;
    %test_date(date=SCREEN, comp1= le, comp2= le, label='SCREEN');
run;

data test4;
    variable1=0;
    %test_date(date=SCREEN, comp1= le, comp2= le, label='SCREEN');
run;

/*  Macro variables are empty. Outer if is false. The macro does nothing.  */
%let datein=;
%let st_screen=;
%let ed_screen=;


data test5;
    variable1=1;
    %test_date(date=SCREEN, comp1= le, comp2= le, label='SCREEN');
run;

data test6;
    variable1=0;
    %test_date(date=SCREEN, comp1= le, comp2= le, label='SCREEN');
run;
0
votes

Your program does not make any sense. If we ignore the %IF statements that are just potentially generating messages to the LOG your macro is generating this SAS code:

if &datein. ne "" and ST_&date. ne "" then do;
  if ( AND  ) then EPOCH=&label.;
end;

Since you are using the variable AND as the condition for the IF statement SAS will assume that it is a numeric variable and test whether its value is non-zero and non-missing. If there is no variable named AND then its value will be missing so the value of EPOCH will never be changed.

If you want the macro to do those tests of macro variable lengths then pull that macro logic out of the middle of the SAS code you are trying to generate.

Let's look at the first %IF/%THEN statement.

%if %length(&datein.)=10 OR %length(ST_&date.)=10 
  %then %put ST_&date._10 &comp1. datein_10; 
%else %put ST_&date._19 &comp1. datein_19;

So you are testing if the length of the macro variable DATEIN is 10 bytes or the length of the macro variable DATE is 7 bytes (the constant text ST_ will always be 3 bytes long).