1
votes

Can anybody tell me why this isn't resolving:

/*put all transaction table names into a data set*/ 
/*(table names are of format transac_20130603_20130610 (date from and date to)*/
data transaction_tables;
    set SASHELP.VTABLE (keep=libname memname);
    where lowcase(substr(memname,1,8))='transac_'

run;
/*sort and add rownumbers*/
proc sql;
create table transaction_tables as
    select *, monotonic() as rownum
         from transaction_tables
             order by memname;
run;
/*find rownumber of first and last transaction tables with run dates before campaign start and after end date of campaign*/
data _NULL_;
set transaction_tables;
    if substr(memname,9,8)<=&pre_period_start. and substr(memname,18,8)>=&pre_period_start. then do;
        call symput("r1", rownum);
        stop; 
        end;
run;        
data _NULL_;
set transaction_tables;
    if substr(memname,9,8)<=&max_enddate. and substr(memname,18,8)>=&max_enddate. then do;
        call symput("r2", rownum);
        stop;
        end;
run;
%put &r1; %put &r2;
/*r1 = 11, r2 = 27 - both resolving OK*/

/*get all relevant transaction table names where rownumbers are between r1 and r2*/
/*r1=11 and r2=27 so my transaction table name macros should run from t_0 to t_16/*
%macro trans;
%let y = %eval(&r2 - &r1);
%do i=0 %to &y;
data _NULL_;
set transaction_tables;
    if rownum = &r2 - (&r2 - &r1 - &i)  then do;
        call symput("t_&i", cats(libname, '.', memname));
        stop; 
        end;
%end;
%mend trans;
%trans;

%put &t_0;
--WARNING: Macro variable "&t_0" was not resolved

i'm not entirely sure why but from messing around with a few of the variables i think the problem lies with the last part where it is attempting to assign table names to t_&i macros. i think the issue is with trying to name a macro variable while trying to call another macro variable (trying to create macro t_0 by calling &i when i=0). i guess i've screwed something up with the syntax because i think the logic is fairly sound.

thanks!

2
A good approach to solving a macro problem is to make the code execute without the macro. All you are doing is code substitution...do it the long way to make the code execute, start putting in the macro code a little at a time.Jay Corbett

2 Answers

1
votes

Without judging the usefulness of what you're trying to do:

It is a scope issue. Any macro variable you create within a macro, only exists within that macro. If you want it to exist outside your macro, you either need to:

  • Create the macro variable in open code (not in a macro) and before you execute the macro.
  • Set it explicitly to global within your macro (before the first mention of it), you do this by writing:

    %global t_0;

edit Also note that to end a proc sql, you need to use quit instead of run.

1
votes

Alternative approach:

proc sql;                                                                                                                               
create table result as                                                                                                                  
    select cats(libname,'.',memname) as desired                                                                                                      
    from dictionary.tables                                                                                                                  
    where substr(libname,1,8)='TRANSAC_'     
    and (scan(libname,2,'_')<=&pre_period_start. and scan(libname,3,'_')>=&pre_period_start.) 
    and (scan(libname,2,'_')<=&max_enddate. and scan(libname,3,'_')>=&max_enddate.) ;

data _null_;
    set result;
    call symput(cats('R_',_n_),desired,'g');
run;

This could even be rewritten as one step using the SQL 'into' clause. The SQL quit; statement is optional, personally I never use it.