0

Hi I have a program to use one macro to call another one.

I have two month(jun12 and jul12) and each month has two parts(1 & 2), I want to do a loop which I construct a macro called"Loop", Inside it, I constructed a Array, and used Do comment do call a macro "try".

Seems like it doesn't work. Can someone help me with it? Thank you!

 LIBNAME EC100006 "G:\sample";
%MACRO try(month=,part=);
      ...FROM EC100006.monthitsum&month.lag&part AS t1
%MEND try;

%Macro test;
    ARRAY Mon(2) jun12 jul12;
    %Do i=1 %to 2;
        %Do j=1 %to 2
            %try(month=Mon(i),part=j)
        %End
    %End
%Mend test;

%test
Joe
  • 62,789
  • 6
  • 49
  • 67
user1652926
  • 85
  • 2
  • 5
  • You have `ARRAY` here but no associated data set? Are you trying to retrieve values (jun12 jul12) from other data set? Also it is `%try(month=Mon(&i),part=&j)` as you are referring macro variables. – Robbie Liu Nov 28 '12 at 11:12

2 Answers2

0

You can't have an array of macro variables.

The simplest way to repeatedly call a macro with a list of parameters is to make a dataset with those parameters and call it from the dataset, either with CALL EXECUTE or using PROC SQL to create a macro list of macro calls.

data call;
input month $ part;
datalines;
jun12 1 
jul12 2
;;;;
run;

proc sql;
select cats('%try(month=',month,',part=',part,')') into :mcalllist 
  separated by ' ' 
  from call;
quit;

&mcalllist;

That only works if you have less than 20,000 characters worth of calls or so - if it's more than that you need to try a different option (%include file or call execute).

Joe
  • 62,789
  • 6
  • 49
  • 67
  • Thank you! I used your code with my try macro, seems like it can not read the input file. The log error is like this NOTE: Line generated by the macro variable "PART". 1 EC100002.._al_1_part_1_lag -- 22 200 ERROR 22-322: Expecting a name. ERROR 200-322: The symbol is not recognized and will be ignored. – user1652926 Nov 29 '12 at 16:31
  • Other than correcting the input statement in my example dataset to include a $ after month, the example code works as expected. The error you posted often suggests you have something else missing in your code, as it means it's hitting data step code or something else outside of a datastep - perhaps you need to put the &mcalllist call inside a PROC or a data step? – Joe Nov 29 '12 at 17:05
  • So by saying "less than 20,000 characters worth of calls ", do you mean the dataset size cannot bigger than 20,000 characters? And if I want to make the program more automated. In other words, the user can just tell the program the starting month and the end month and the program can do teh loop automaticly? For eample, I tell the program the begining month is May and the end month is Aug, and each month has two parts. Do I need to construct a month library and rank them? – user1652926 Nov 29 '12 at 17:39
  • No. What you're doing here is constructing a macro variable that consists of `%try(x,y) %try(a,b) %try(d,f)`. That macro variable has a maximum size - around 20,000 characters itself. So if each call is about 20 characters long, you can have up to 1000 different calls in that macro variable. You'll get a warning if that's happening. The dataset size that you're using the macro call on is not important. – Joe Nov 29 '12 at 17:44
  • If you want to do this programmatically, you would want to construct a dataset that matches what you want to call - you could ask the user to do this, I would think. However, you could also instruct an outer macro to create it - not with macro code though, but with a normal datastep inside the macro. – Joe Nov 29 '12 at 17:46
  • Sorry I have another question. What it I define the array outside the macro? I tried, but it doesn't work. What reason do you think it might be? – user1652926 Nov 29 '12 at 18:25
  • Why are you using an array? You don't need to use an array to do what you're doing. – Joe Nov 29 '12 at 18:37
  • I'm trying to make it more automatic.So the user just need to type in the beginning month and ending month, and the program will do the loop. – user1652926 Nov 29 '12 at 20:07
  • An array does _not_ help you there. You need a row-wise solution. Something like: `data call; do month = &startmonth to &endmonth; do part=1 to 2; output; end; end; run;` Then you can take that call dataset and run it from my code above. – Joe Nov 29 '12 at 20:18
  • And my month will looks like dec11,jan12,feb12,.... I remember SAS have a way to rank them but I don't know how to do it. Can you help me with it too? Sorry to bother you so many times. – user1652926 Nov 29 '12 at 21:51
  • MONYY format will give you dates that look like that, or you can roll your own format (it would be somewhat complex to formulate a DO loop that used dates once per month). – Joe Nov 29 '12 at 22:16
  • Do I need to define them in the data or in the try macro parameter part? – user1652926 Nov 29 '12 at 22:28
0

So right now it's something like this

LIBNAME EC100006 "G:\sample";
%MACRO try(month=,part=);
  ...FROM EC100006.monthitsum&month.lag&part AS t1
%MEND try;

Data Array
ARRAY Mon{2} jun12 jul12;
RUN;
%Macro test;
    %Do i=1 %to 2;
    %Do j=1 %to 2
        %try(month=Mon(i),part=j)
    %End
%End
%Mend test;

%test
user1652926
  • 85
  • 2
  • 5