Search code examples
sasmacrossas-macro

SAS Running Multiple Macros based on Variable value passed through as a list


I have a query where I need to run multiple macros based on a condition. The condition is that if the value of a variable is X then macro 1 should run, if the value of the variable is Y then macro 2 should run and so one. I am trying to pass the value of the variable as a list. But only the 'discount_edd' macro is running. I don't see any particular error in the code. I haven't declared the variable 'buriza' anywhere else in the code except the place where you directly see it. Here is the code for the same. I am passing 'Discount_EDD' and 'Discount_Logility' as the inputs to the '&list_string' macro variable and want the macro 'dummy' to run both the discount_edd and discount_logility macros from the macro named 'doit'.

%put &list_string;
%put &buriza;

%macro get_bds;
{code to get data from excel files stored on servers}
%mend;

%macro discount_edd; 
{proc sql statements to get Discount data from teradata SQL}
%mend;

%macro discount_logility;
{proc sql statements to get Discount data from DB2 SQL}
%mend;

%macro doit(list=);
  %if "&buriza."="Discount_EDD" %then %do;
    %discount_edd
  %end;
  %else %if "&buriza."="Discount_Logility" %then %do;
    %get_bds
    %discount_logility
 %end ;
%mend doit;

%macro dummy(bur= );
   %do i = 1 %to %sysfunc(countw(&list_string.));
      %let buriza = %scan(&list_string., &i.);
      /*%let list_string=Discount_EDD;*/
      %doit(list=&buriza)
   %end;
%mend dummy;
options mprint;
%dummy(bur= &list_string)

Here is the part of the log of the output

LIST_STRING=Discount_EDD
 LIST_STRING0=2
 LIST_STRING1=Discount_EDD
 LIST_STRING2=Discount_Logility
 LIST_STRING_COUNT=2
MLOGIC(QLEFT):  %LET (variable name is I)
MLOGIC(VERIFY):  Beginning execution.
MLOGIC(VERIFY):  This macro was compiled from the autocall file /opt/../verify.sas
MLOGIC(VERIFY):  Parameter TEXT has value  
MLOGIC(VERIFY):  Parameter TARGET has value  
MLOGIC(VERIFY):  %LOCAL  I
MLOGIC(VERIFY):  %IF condition %length(&text)=0 OR %length(&target)=0 is FALSE
MLOGIC(VERIFY):  %DO loop beginning; index variable I; start value is 1; stop value is 1; by value is 1.  
MLOGIC(VERIFY):  %IF condition NOT %index(&target,%qsubstr(&text,&i,1)) is FALSE
MLOGIC(VERIFY):  %DO loop index variable I is now 2; loop will not iterate again.
MLOGIC(VERIFY):  %IF condition &i>%length(&text) is TRUE
MLOGIC(VERIFY):  Ending execution.
MLOGIC(QLEFT):  %IF condition &i is FALSE
MLOGIC(QLEFT):  Ending execution.
MLOGIC(DATATYP):  %LET (variable name is LEN)
MLOGIC(DATATYP):  %IF condition &len > 0 is FALSE
MLOGIC(DATATYP):  Ending execution.
MLOGIC(STPEND):  %IF condition (%qcmpres(&_RESULT) eq PACKAGE_TO_EMAIL) and       (%datatyp(&_EMAIL_ADDRESS0) ne NUMERIC) and       (&_EMAIL_ADDRESS0 ne ) is FALSE
MLOGIC(STPEND):  %LET (variable name is MIMEMAP1)
MLOGIC(STPEND):  %LET (variable name is MIMEMAP)
MLOGIC(QCMPRES):  Beginning execution.
MLOGIC(QCMPRES):  This macro was compiled from the autocall file /opt/../qcmpres.sas
MLOGIC(QCMPRES):  Parameter TEXT has value 
MLOGIC(QCMPRES):  %LOCAL  I
MLOGIC(QCMPRES):  %LET (variable name is I)
MLOGIC(QCMPRES):  %DO %WHILE(&i^=0) loop beginning; condition is FALSE.  Loop will not be executed.
MLOGIC(QLEFT):  Beginning execution.
MLOGIC(QLEFT):  This macro was compiled from the autocall file /opt/../qleft.sas
MLOGIC(QTRIM):  Beginning execution.
MLOGIC(QTRIM):  This macro was compiled from the autocall file /opt/../qtrim.sas
MLOGIC(QTRIM):  Parameter VALUE has value 
MLOGIC(QTRIM):  %LOCAL  I
MLOGIC(QTRIM):  %DO loop beginning; index variable I; start value is 0; stop value is 1; by value is -1.  Loop will not be executed.
MLOGIC(QTRIM):  %IF condition &i>0 is FALSE
MLOGIC(QTRIM):  Ending execution.
MLOGIC(QLEFT):  Parameter TEXT has value 
MLOGIC(QLEFT):  %LOCAL  I
MLOGIC(QLEFT):  %IF condition %length(&text)=0 is TRUE

After the revised code only the 'discount_edd' macro runs. I need the 'discount_logility' macro to run too.


Solution

  • This macro definition does not make sense.

    %macro doit(list=);
      %if "&buriza."="Discount_EDD" %then %do;
        %discount_edd
      %end;
      %else %if "&buriza."="Discount_Logility" %then %do;
        %get_bds
        %discount_logility
     %end ;
    %mend doit;
    

    You are defining the macro to take a parameter (which will be a LOCAL macro variable) named LIST. But the macro is only referencing some undefined macro variable named buriza instead of using the value you are passing into it.

    If you want %DOIT to operate on just one value then use the same name for both macro variables:

    %macro doit(buriza);
      %if "&buriza."="Discount_EDD" %then %do;
        %discount_edd
      %end;
      %else %if "&buriza."="Discount_Logility" %then %do;
        %get_bds
        %discount_logility
     %end ;
    %mend doit;
    

    If you want %DOIT to loop over an actual list of values then you would define it his way instead:

    %macro doit(list);
      %local buriza i ;
      %do i=1 to %sysfunc(countw(&list),|));
         %let buriza=%scan(&list,&i,|);
         %if "&buriza."="Discount_EDD" %then %do;
           %discount_edd
         %end;
         %else %if "&buriza."="Discount_Logility" %then %do;
           %get_bds
           %discount_logility
         %end ;
      %end ;
    %mend doit;
    

    Then you could call it with an actual list of values. I have used | as the delimiter between the values since your valid values are already using spaces in them.

    %doit(Discount_EDD|Discount_Logility);