Macro variables inside a macro variable

Accepted Solution Solved
Reply
Contributor
Posts: 60
Accepted Solution

Macro variables inside a macro variable

Hi,

 

I have searched a solution for this but haven't come up with a working one.

What I need is a dynamic title macro variable containing varying amount of macro variables.

Here is an example:

%let t1=some text;

%let t2=some more text;

%let t3=moooooooooorrrrr text;

%let title=&t1 : and here is &t2 and &t3;

 

When I call &title I would like to see a string "some text : and here is some more text and moooooooooorrrrr text. I have tried almost everything including adding "" or '' inside the &title. I guess there must be a %FUNCTION which force resolves these &t1 &t2 &t3 macro variables first.

Thanks!

 


Accepted Solutions
Solution
‎05-03-2016 06:29 AM
Contributor
Posts: 60

Re: Macro variables inside a macro variable

Thank you for your answer.

 

To be honest I am not sure what happened, but now it is working (basically I did nothing that I haven't tried before).

Now I give title=&t1.: &t2. &t3. as input for the %MACRO. Then inside the %MACRO I do this

%let titleprocess=%qcmpres(%bquote(&title));

data text;
text="&titleprocess";
call symput('GTITLE',text);
run;

 

And voila it works....

 

One possible reason (thought had compressed them before too) is that for some other unknown reason proc sql into clause appends million trailing blanks into the macro vars (even when the TRIMMED option is used....). I don't know if that has something to do with the problem or not. So Astounding's point of the leading (also trailing?) blanks might have something to do with the issue.

Thanks all.

 

View solution in original post


All Replies
Super User
Super User
Posts: 7,714

Re: Macro variables inside a macro variable

The function you are looking for is %eval().  However I would say why are you doing it like this.  Put titles in a dataset, this will make manipulation much easier, and your code will be far simpler and easy to maintain.  Base SAS is designed to do data processing, Macro is for generating code.  The approach of a dataset will also help you if you need to validate - the titles and footnotes can be stored, and validated separately from the output.  For example:

data tandf;
  torf="title"; no=1; txt="A title"; output;
  torf="footnote"; no=1; txt="A footnote"; output;
run;

data _null_;
  set tandf;
  call execute(catx(torf,no)||'"'"txt||'";');
run;

Or you could call symput them into macro variables if you really have to.  But the main point is, the titles and footnotes are in a dataset, so you can concatenate, process, replace etc. very easily.

Contributor
Posts: 60

Re: Macro variables inside a macro variable

[ Edited ]

Thank you for your help.

The reason why I would need this is to produce reusable code (which is extremely hard with sas Smiley Happy).

I will have a %MACRO which takes title as one of its input parameters, and those t1,t2 etc. are generated inside the %MACRO (number of "t"s is not predefined the number of them depends on the input data). Because of this I can't "predict" what kind of form does the title get.

I'll give an example:

%macro runthismacro(inputdata=somedata,title=&t1. : &t3 .... &t2);

I would like to get this into a dataset so that I would have:

data data;

length title $100;

text="&title.";

run;

for example. There I would call symput the text into a "already resolved" version of the initial input. This step is just to clarify the resolving process (in practice it is just an additional unnecessary step).

However I am not able to get the &title. to resolve its contents inside the "text" variable.

 

Hope this explains my problem a bit better.

 

EDIT: I would add that the user will know the form of the title (and how many "t"s there will be), but the %MACRO can't. So thats why I need the title as an input parameter.

Super User
Super User
Posts: 7,714

Re: Macro variables inside a macro variable

My question remains, why have titles in the given macro parameters:&Tx?  That is the problem.  Do remember that in the SASHELP.VMACRO view, you will see all defined macros and what they resolve to so you could just say:

data want;

  set sashelp.vmacro (where=(char(name)="T"));

run;

 

But again, the whole problem arises from putting Data in macro variables.  I mean what happens when your user puts special characters in the MVar?   Or a long string?  Etc.  Putting it in a dataset resolves all that.

 

Contributor
Posts: 60

Re: Macro variables inside a macro variable

[ Edited ]

Thanks a lot for the sashelp.vmacro tip, I wasn't aware of that probably I will get it working with that.

 

And the reason why the title needs to be a macro variable of  macro variables is that the %MACRO loops through the data (produces multiple graphs from subsets of input data). And the t1,t2 etc. contains the current value of the "by" variables which are used for the subsetting. So in other words the title changes throughout the %MACRO itself.

 

EDIT: And I would also like to add that yes they can contain special characters, but I can handle them with %BQUOTE or some other functions.

Super User
Super User
Posts: 7,714

Re: Macro variables inside a macro variable

Ah, so again your fighting the Base SAS with a macro work-around.  Base SAS has something called by group processing, which will do exactly what you want.  There are several forms, but a simple example:

proc sort data=sashelp.class out=class;
  by sex;
run;
proc report data=class;
  by sex;
  title "#byval1";
  columns name age height weight;
run;

You will note the two lines: by <vars>; and title "#byvalX".  These relate to each one so you can have as many by groups as you like, and you can put any other text you like in that: title "The group is: #byval1";  You can also use byvar.

Tagsets excelxp has a sheet interval option which can be set to bygroup etc. 

Contributor
Posts: 60

Re: Macro variables inside a macro variable

Thank you, but in my case that is not a solution since the %MACRO is quite complicated I would say (and you are right and I admit that I have a tendency of trying to mimic/bend "OOP approaches" with macro facilities).

I wasn't aware of the # reference, and that is surely a really useful knowledge in many occasions, so really happy to learn that Smiley Happy

However like I said the situation is a bit more complicated than usually. One thing is that I have to use GTL graphics, and while this your method might be implemented there also I am pretty sure it is much more complicated to implement than a macro approach (or requires more work). And if SGRENDER happens to support the BY statement (haven't checked that) even then it probably won't fit my needs because of the structure of the output.

In my case the keywords are DYNAMIC and REUSABLE and often the dynamic part throws me off into the macro world (like I mentioned earlier this is probably because of my limited SAS knowledge).

Thanks again for your tips, they will become handy in future for sure. And maybe I will investigate if this approach could be implemented on my code.

 

Super User
Posts: 5,362

Re: Macro variables inside a macro variable

Based on your original post, the resolution should be taking place.  First, consider the "obvious" possibilities:

 

Are you using single quotes around '&title'?  (I suspect you are in the clear here.)

 

Are all the macro variables already defined by the time you use them?  (This may be an issue.)

 

Does &title contain more than 100 leading blanks?  (I doubt it.)

 

At any rate, you may need a somewhat more complex approach:

 

%macro runthis macro (title=t1 t2 t3, inputdata=somedata);

 

Then inside the macro, build the title string.  Retrieve "t1", put an ampersand or three in front of it, to get the current value of the macro variable named "t1".  Then repeat for the names of the other macro variables in "t1 t2 t3".

 

There is absolutely nothing wrong in the original post you presented.  Those macro variables should be resolving without requiring a function.

Solution
‎05-03-2016 06:29 AM
Contributor
Posts: 60

Re: Macro variables inside a macro variable

Thank you for your answer.

 

To be honest I am not sure what happened, but now it is working (basically I did nothing that I haven't tried before).

Now I give title=&t1.: &t2. &t3. as input for the %MACRO. Then inside the %MACRO I do this

%let titleprocess=%qcmpres(%bquote(&title));

data text;
text="&titleprocess";
call symput('GTITLE',text);
run;

 

And voila it works....

 

One possible reason (thought had compressed them before too) is that for some other unknown reason proc sql into clause appends million trailing blanks into the macro vars (even when the TRIMMED option is used....). I don't know if that has something to do with the problem or not. So Astounding's point of the leading (also trailing?) blanks might have something to do with the issue.

Thanks all.

 

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 8 replies
  • 495 views
  • 0 likes
  • 3 in conversation