I can call the macro VIO
by %VIO(Dow=Fri,Hour=8)
without error. Now I want to nest the call macro inside a do loop.
Here's what I have tried but no luck.
%macro trythis;
data _null_;
array ay[3] $3 ('Fri' 'Sat' 'Sun');
%do i = 1 %to dim(ay);
%do j = 1 %to 24;
%VIO(ay[&i],&j);
%end;
%end;
run;
%mend;
%macro VIO(Dow,Hour);
data Want&Dow.&Hour;
set have(where=(hour="&Hour"));
format dow $3.;
dow = "&Dow";
run;
%mend;
It seems ay[&i]
will resolve to ay[1]
not Fri
.
You can't exchange data with macro variables that way. Macro variables and macro calls resolve before the data step is even compiled, not to mention run. This is nice because it allows macro variables and macros to affect the data step compilation (ie, define which columns are present, for example). It also means you can't do what you're trying to do. Despite its similarities, the SAS Macro language is not a method of writing functions in SAS. You can write certain function-style macros, but that's not the same thing.
You don't specify what your macro does, so it's difficult to fully answer how to fix this.
If your macro takes a value and does things with it in the macro language, and you need to interact with the data step, you have several options:
If you don't need to interact with the data step, this may be easier to do.
Macro Arrays aren't quite the same as data step arrays. They're not an actual feature of the programming language; they're a hack. You can search for papers on them on the internet; for example, Tight Looping with Macro Arrays explains one example.
The general principle, though, is very straightforward. You use multiple ampersands to multiply resolve something.
%let ay1 = Fri;
%let ay2 = Sat;
%let ay3 = Sun;
%let i=2;
%put &&ay&i.;
This will resolve as you expect. The double ampersand tells SAS to delay resolution one pass, so &&ay&i
becomes &ay1
when &i
resolves but the double &&
just changes to a single &
and ay
is left alone.
So you can do something easy with the do loop:
%macro trythis;
%let ay1=Fri;
%let ay2=Sat;
%let ay3=Sun;
%do i = 1 %to 3;
%do j = 1 %to 24;
%VIO(&&ay&i.,&j);
%end;
%end;
%mend;
Now, I want to state very clearly: the general approach you are taking here is very likely a poor one, both from an easy-to-program point of view and a speed point of view. You don't give visibility to %vio
, so it's hard to say what you're doing or what the right approach is, but this is very likely not the right one. At minimum, splitting all of the parts up into three or four macros that clearly substantially interdepend will lead to complexity to maintain, and repeatedly running a datastep with a single where clause is very, very slow.