tags:

views:

175

answers:

3

I'm using SAS 9.1.3 to call a macro in a DATA step, but the macro generates a PROC REPORT step, so I am using CALL EXECUTE to call it, generate all those PROC REPORT steps, and then execute them all after the DATA step.

I'm using an array, and the macro is executed each time for every element in this array:

DATA macro_test;
  ARRAY questions[3] $ 32 ('question1' 'question2' 'question3');

  DO i=1 to 3;
    a_question = questions(i);
    CALL EXECUTE( "%report_by_question(a_question)" ); 
  end;

RUN;

The thing is, the report outputs are coming out (usually) backwards - it will print question3 first, then 2, then 1.

Is there a way to modify the execution order of CALL EXECUTE so I can have the question reports print in order, or does it just do its own thing?

Thanks!

+5  A: 

I assume you mean something more like this for yout call execute() line:

 CALL EXECUTE( "%report_by_question(" || trim(left(a_question)) || ");" );

With a test macro I get some log lines like this, showing that the call execute()s are happening in the right order. Do you get anything similar?

Macro

%macro report_by_question(a);
data test_&a;
  do i=1 to 10000000;
    output;
  end;
run;
%mend;

Logs

NOTE: CALL EXECUTE generated line.
1   + data test_question1;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION1 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           6.14 seconds
      cpu time            0.45 seconds


1   +                                                                   ;
2   + data test_question2;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION2 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           3.87 seconds
      cpu time            0.53 seconds


2   +                                                                   ;
3   + data test_question3;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION3 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           3.12 seconds
      cpu time            0.45 seconds
Simon Nickerson
Yep, haha, forgot the whole concatenate on the variable ;)So yes, I get the correct order of steps being generated in the log, but when they start being spit out in the output, they are in what looks totally random order (I'm using 5 questions as a test now).
chucknelson
OK - I just did a test and did ODS to HTML, and there the report tables are in the right order. I don't understand why ODS LISTING would put them in the output in a different order.
chucknelson
CALL EXECUTE's are working fine and in order - just wrapping this question up!
chucknelson
+1  A: 
adam
Thanks for the insight, haven't gotten to "macro language" yet in SAS ;) That example above was just simplified to explain my problem. I'm using a DATA step to loop through things, and reading in a variable/question data set - not hard-coding this stuff, haha.
chucknelson
+2  A: 

A data step is compiled and then executed. The call execute(str); pushes the str into the input queue, so that they are popped after the data step is done execution. The order is preserved, period.

However, if you put your macro invocation in the double quoted string as you do in: call execute("%report(q)"); then the macro is invoked when the data step is compiled, which is even before the data step starts running.

If you don't want to invoke the macro in the compile time, then either macro quote it or put it in the single quoted string. Below is an example. Hope this helps.

/* create a dataset with 1 var and 3 obs */
data qs;
  input q $;
cards;
q1
q2
q3
;
run;

/* reporting macro -- a mockup */
%macro report(q=);
  %put report for q=&q;
%mend  report;

/* call the reporting macro for each q */
data _null_;  
  set qs;     
  macro = catx(q, '%report(q=', ')'); 
  call execute(macro);
run;

/* on log
report for q=q1
report for q=q2
report for q=q3
*/


/* to show what happens when the
   macro is invoked during the compile
   time */
data _null_;
  call execute("%report(q=q1)");
  put "after call execute";
run;
/* on log
1   data _null_;
2     call execute("%report(q=q1)");
report for q=q1
3     put "after call execute";
4   run;
after call execute
*/
Chang Chung