Using parameters is not the only way to pass values to a macro. You can pass them using a sas dataset if you have designed you macro to accept them. You can make it work such that the variable names are the parameter names and the values in the variables are the parameter values. Then, in your macro, you use it just like you had parameters with parameter values. It makes sense to do it this way when you have a lot of parameters that have to be set. Using a dataset makes it is easier to document your settings. You can have a standard "set" of settings in a dataset that can be distributed. You can specify your "changing" settings at the top of your code, in a data step, where it is easy to notice, rather than specify them at the end of your code where you call a macro after preparing your input data.
I like to give real-life examples so here is the parameter dataset I
set up. Actually, there is not just one parameter dataset -- there
are TWO !!
| data rgpp_style;
*- do not change any of these variable names or their characteristics -; length cback cstripe cscale $ 8 fitemtext fitemdesc fblockdesc fpatient $ 32 citemdesc citemdesctrunc cblockdesc cpatient citemtext cfigure $ 8 cblockbox $ 8 cblockdescbg cpatientbg $ 8 hitemdesc hblockdesc hpatient hitemtext hfigure hscaletext 8 drawblockbox uniformscale usearrows 8 ypixels xpixels vpos hpos 8 hposdmin hposdmax hposdmean hposminfigwidth hposmingap 8 maxucletters maxmcletters 8 ; *- Size of html output with number of rows and columns. -;
*- Start and end hpos positions for date area. The maximum
-;
*- Colors of the background and stripes across the date area
-;
*- Font, color and height of text displayed on the left of
the date area -;
*- Height, font and default color of the text to use when
text values -;
*- Maximum upper case and mixed case letters that you know
will -;
*- Font, color, height and background color of Patient top-of-page
title -;
*- Font, color, height and background color of block titles
-;
*- Whether or not to draw a box around each block of information
displayed -;
*- Height and color of the time scale to draw.
-;
*- Whether the time ticks on the scale should be uniformly
spaced. -;
*- Whether to use arrow heads to point to start or end day
values -;
*- Height and color of the figures. Height is effectively
the -;
*- This is the minimum width in hpos values that you want
for -;
*- hposmingap is a control used when you are displaying text
-;
run;
data rgpp_global;
*- Name of the unique patient identifier variable present
-;
*- Destination folder for the html files and gif files -;
*- Set this to your scale you want to show on the time axis.
They should be pairs -;
run; |
Running the above code just creates a dataset. It does not create any
macro variables. I ran that code and afterwards checked for what global
macro variables were there and this is what I got. I got no global
macro variables.
| 624 %put _global_;
|
I know that my parameter dataset contains both numeric variables and
character variables. I also know it does not contain variables with the
unlikely names of "__i", "__y", "_num" or "_char". So here is my
code for "symput"ing out all the variables and their values. Note that
I have to use a merge statement, without any "by" variables, as
I have two datasets but want only one collective observation.
| data _null_;
merge rgpp_style rgpp_global; array _num {*} _numeric_; array _char {*} _character_; length __y $ 32; do __i=1 to dim(_char); __y=vname(_char(__i)); call symput(__y,trim(left(_char(__i)))); end; do __i=1 to dim(_num); __y=vname(_num(__i)); call symput(__y,trim(left(_num(__i)))); end; run; %put _global_; |
....and here is what I got in the log.
| 688 data _null_;
689 merge rgpp_style rgpp_global; 690 array _num {*} _numeric_; 691 array _char {*} _character_; 692 length __y $ 32; 693 do __i=1 to dim(_char); 694 __y=vname(_char(__i)); 695 call symput(__y,trim(left(_char(__i)))); 696 end; 697 do __i=1 to dim(_num); 698 __y=vname(_num(__i)); 699 call symput(__y,trim(left(_num(__i)))); 700 end; 701 run; NOTE: Numeric values have been converted to character values at
the places given by:
702
|
You can see that all the dataset variables have been turned into global macro variables and their values are now the global macro values.
What I am going to do next is to show you how you can have a macro access these two parameter datasets using the code above and you will see that these macro variables are local to the macro. This is the ideal situation because it means these parameter datasets really are acting like parameters and their settings and their values will not affect anything outside the calling macro. Firstly, there is something I have to warn you about. The macro variables will only be local to the macro if the macro has at least ONE parameter. That's the way "call symput" works. You don't have to use this parameter - you just have to declare it. I know that what we are trying to do is to pass all parameters and their values in datasets, and not call the macro with any parameter settings, but you need one parameter declared with the macro (at least) for the scope of "call symput" to be local. I will be using a positional parameter named "dummy" for that that I won't refer to in my code. You need to remember that rule if you are doing serious macro programming using parameter datasets. The way it is explained in the sas documentation is "SYMPUT puts the macro variable in the most local nonempty symbol table". So in our macro we need to make sure it has something in its "symbol table" so that the "call symput"s will scope the macro variables in the macro. There is more in the sas documentation on this. Also read up on "call symputx" when you have time.
One more time - note that I used a dummy parameter in the macro
definition. I did this to keep the "call symput"s local. Without
the dummy parameter, they would be global.
| 152 %macro mymacro(dummy);
153 data _null_; 154 merge rgpp_style rgpp_global; 155 array _num {*} _numeric_; 156 array _char {*} _character_; 157 length __y $ 32; 158 do __i=1 to dim(_char); 159 __y=vname(_char(__i)); 160 call symput(__y,trim(left(_char(__i)))); 161 end; 162 do __i=1 to dim(_num); 163 __y=vname(_num(__i)); 164 call symput(__y,trim(left(_num(__i)))); 165 end; 166 run; 167 %put >>>>>> inside "mymacro" these are the user macro variables >>>>>; 168 %put _user_; 169 %mend mymacro; 170 %mymacro 171 172 %put >>>>>>> ouside "mymacro" these are the global macro variables >>>>>; NOTE: Numeric values have been converted to character values at
the places given by:
>>>>>> inside "mymacro" these are the user macro variables >>>>>
|
Go back to the home page.
E-mail the macro and web site author.