Help using Base SAS procedures

Macro within a Macro

Reply
Regular Contributor
Posts: 173

Macro within a Macro

Hello everyone,

I have created a macro (supp_waterfall) which is used to calculate the number of records dropped (RecDrop) at every suppression step. There are 16 suppression steps so the macro will be executed 16 times.

The goal is to create 16 macro variables holding 16 drop counts. But I am not sure how to create and keep these 16 macro variables and their values. I would like to use them to calculate the drop total later in the program.

Below is the portion of the code related to the drop count variable:



%macro supp_waterfall (supp_file, supp_out, numstart, rptorder);
/*pass in the input file, output file, record begin, report order */

data &supp_out
set &supp_file;
if _n_=1 then do;
~~
RecDrop=&numstart-RecKept;
CALL SYMPUT('Drop&rptorder',RecDrop);
~~
%mend;

%supp_waterfall(&supp_file, &supp_out, &numstart, &rptorder1, &numrecs);



RecDrop is the variable I would like to keep for each of the 16 times this macro is executed. I have no idea how to create a macro variable for it so I tossed in the 'call symput' in there. I get syntax error for it.

I attached '&rptorder' to the end of the variable DROP as an unique identifier for the 16 drop counts. So &rptorder goes from 1 to 16. rptorder is hardcoded and passed into the macro. Everything works except the CALL SYMPUT statement, which gives me a syntax error.

I hope i have given enough information for anyone to trouble shoot. Any suggestions will be greatly appreciated.

Thank you!
Super Contributor
Super Contributor
Posts: 3,174

Re: Macro within a Macro

Suggest you run your code with the following to get the most diagnostics output:

OPTIONS SOURCE SOURCE2 MACROGEN SYMBOLGEN MPRINT;

First, you are going to have issues when you do not code a RUN statement to let SAS compile up to the point in your code.

But, also, you are not incrementing &rptorder anywhere in code you have shared. I would expect this component to be most important.

Without details (which are also important for forum replies), it's likely you are getting some macro variable error or macro compilation error.

Lastly, you show a macro supp_waterfall being invoked but with macro variables being supplied to the macro invocation -- again, we don't see what leads up to the subordinate macro invocation, which is critical for decent feedback and guidance without guessing or speculating too close to the margin.

Scott Barry
SBBWorks, Inc.
Super Contributor
Super Contributor
Posts: 3,174

Re: Macro within a Macro

Recommend you implement the suggestion OPTIONS statement, run your code a few times, possibly even setup your code-path without the "help" of macro processing - this suggestion helps validate that you have a workable program flow before introducing the macro language challenges. So, some self-directed desk-checking with no macro, then maybe go macro and again more testing with max diagnostics turned on for effect, and follow the program flow. If you then have issues or concerns, re-post a reply with copious SAS log output diagnostics and warnings / errors intact so others can assist your quest.

Scott Barry
SBBWorks, Inc.
Regular Contributor
Posts: 173

Re: Macro within a Macro

Hi sbb,

My code has the OPTIONS and the RUN statements as you suggested. I did not include them at the beginning of my post to reduce the size of it. The increments are working fine. For clarification purposes, here is the code that evokes the macro at the second step:


%let supp_file = newbase;
%let supp_out = supp_noPAPCIT;
%let rptorder2 = 2;

%supp_waterfall(&supp_file, &supp_out, &numstart, &rptorder2);

Here are some of the fields produced by the macro:

RecKept: 36616
RecDrop: 1270
Drops: Drop 2

Everything looks right except the very last field "Drops". I would like to see a numeric value in it...ths actual drop count.

I guess my real question is how do I assign a numeric value to a macro variable within a macro. Does this clear things up a little?

Thanks.
Super Contributor
Super Contributor
Posts: 3,174

Re: Macro within a Macro

Suggest you share all of your code and preferably within a SAS execution session to help with anyone's debugging - also, you may want to consider inserting statements like (you assign unique nnn value for each putlog referenced):

putlog '>diag-nnn>' / _all_;

These helpful diagnostics will generate SAS data step variable values along the way with your program.

Also, here's another that will help you:

%PUT _GLOBAL_;

..or..

%PUT _LOCAL_;

..or..

%PUT _ALL_;

Frankly, it's guess-work without suitable code and preferably after SAS log generated messages for helpful reference, both to yourself and the forum readers.

Scott Barry
SBBWorks, Inc.
Regular Contributor
Posts: 173

Re: Macro within a Macro

I have modified my call symput statement a little as follows:

drops = 'Drop'||&rptorder;
CALL SYMPUT('Drops',RecKept);

The first time the macro gets executed the value of Drops is 'Drops 1'.
My goal is to have a variable at the first step called 'Drops1' with the value of 1203 (the drop count). How would I change this code to assign the value 1203 to the variable Drops1?

Thank you!
Super Contributor
Posts: 474

Re: Macro within a Macro

I still didn't get what you are trying to do, but...

This...
[pre]
drops = 'Drop'||&rptorder;
CALL SYMPUT('Drops',RecKept);
[/pre]
will result on assigning the value of the RecKept dataset varialbe to the macro variable named Drops.

If you are trying to assign a value to a macro variable which the name corresponds to the value of the dataset variable Drops, you should do it the following way (I'm assuming that the macro variable rptorder resolves to: 1):
[pre]
drops=cats('Drop',"&rptorder"); * concat Drop&rptorder and trim blanks;
call symput(drops,RecKept);
[/pre]
If rptorder resolves to a dataset variable name, just remove the double quotes around it.

This will assign the value of the dataset variable RecKept to the macro variable named Drop1.

Hope it helps.

Cheers from Portugal.

Daniel Santos @ www.cgd.pt
SAS Super FREQ
Posts: 8,740

Re: Macro within a Macro

I agree with Peter. I'm still not convinced you need a macro program. Also, I'm not sure what you want to do with your CALL SYMPUT, but one of the rules of macro programming is that you cannot CREATE a macro variable with CALL SYMPUT and then USE that same macro variable in the same data step program. A step boundary has to occur before you can USE the macro variable that was created with CALL SYMPUT.

So, depending on your design and what you want to do and your other statements in the macro program, you might have issues with the macro variable that you're trying to create. ... IF you need a macro program at all.

cynthia
Regular Contributor
Posts: 173

Re: Macro within a Macro

Thank you everyone for your input!

This has become more complicated than I anticipated. So I decided to do this without using a macro... You guys are right!

Thank you again !!
Valued Guide
Posts: 2,174

Re: Macro within a Macro

Kevin

Is there some special reason you want to do all this as a macro?
I see no reason it could not all be done in a data step.
But you see a bigger picture, so would you like to explain ... why "macro"

PeterC
Ask a Question
Discussion stats
  • 9 replies
  • 188 views
  • 0 likes
  • 5 in conversation