DATA Step, Macro, Functions and more

referencing macro variables from within macros

Posts: 47

referencing macro variables from within macros

array time_interval{4}$ 10 ('month','month3','annual','ytd');
do i=1 to 4;

Hi all,

In the abover code the macro get_calcs appends variables with month or whichever name you parse onto it (and it works when i send it when individually typed as month, month3 etc.). However, when I use the array it takes it to be the literal array name instead of value. How do I get arround this?

I do know that this has a lot to do with the fact that macros are invoked before the rest of the code. I just want a work around preferably using arrays.

I've used call execute but without success since it executes AFTER the data step where the variables are out of scope. does retain help the situation?
Super Contributor
Super Contributor
Posts: 3,174

Re: referencing macro variables from within macros

You really need to share all of your SAS executed coded - consider this SAS statement to generate the most output that will be useful for your own desk-checking and also for the forum.


Scott Barry
SBBWorks, Inc.
Posts: 8,742

Re: referencing macro variables from within macros

This latest question seems to be related to your other postings:

It's not fair to folks to post bits and pieces of the code in other forum postings, instead of sticking with one post and providing complete information there. For example, the code for %get_calc is needed; the LOG messages are needed; some idea of the data is needed; and some idea of the big picture of what you're trying to achieve will all help other folks come up with constructive and meaningful suggestions.

I've been reading your posts and it's still not clear to me what you are trying to achieve.

However, consider this "fake data" and a macro program that uses a provided suffix in order to create different statements for the compiler, as shown in the SAS log. To simplify things, I removed the array reference and the DO loop -- as they are just an added layer of distraction from the basic point -- that the macro facility is only resolving code and sending the resolved code (without macro variable references) to the compiler. Assume the dataset created from this data is called WORK.FAKE_DATA:

ID Country Type Date actual_east predict_east sales_product discount_product
001 CANADA C 01Jan10 7585 7312 15553 .12
002 CANADA C 01Feb10 9581 9401 22485 .11
003 GERMANY C 01Jan10 9785 8771 21283 .11
004 GERMANY C 01Feb10 6302 6226 12333 .17
005 USA C 01Jan10 7916 7788 14926 .18
006 USA C 01Feb10 9615 8547 21433 .17

MACRO PROGRAM to generate 1 assignment statement for each suffix:
%macro makestmt(suff=);
%if %upcase(&suff) = EAST %then %do;
newvar_&suff = (actual_&suff - predict_&suff) / predict_&suff;
%else %if %upcase(&suff) = PRODUCT %then %do;
profit_&suff = sales_&suff * (1 - discount_&suff);
%mend makestmt;

INVOKE the Macro Program in a DATA step program:
options mprint=1;
data newvar;
set fake_data;

proc print data=newvar;
title 'After using Macro to make new variables';

SAS Log from running the above program:
1048 options mprint=1;
1049 data newvar;
1050 set fake_data;
1051 %makestmt(suff=EAST)
MPRINT(MAKESTMT): newvar_EAST = (actual_EAST - predict_EAST) / predict_EAST;
1052 %makestmt(suff=PRODUCT)
MPRINT(MAKESTMT): profit_PRODUCT = sales_PRODUCT * (1 - discount_PRODUCT);
1053 run;

NOTE: There were 6 observations read from the data set WORK.FAKE_DATA.
NOTE: The data set WORK.NEWVAR has 6 observations and 10 variables.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds

1055 proc print data=newvar;
1056 title 'After using Macro to make new variables';
1057 run;

NOTE: There were 6 observations read from the data set WORK.NEWVAR.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

Notice the MPRINT results. This %IF in the macro program
%if %upcase(&suff) = EAST %then %do;
newvar_&suff = (actual_&suff - predict_&suff) / predict_&suff;

resulted in this resolved statement
being sent to the compiler when the value of the parameter &SUFF was set to EAST.
newvar_EAST = (actual_EAST - predict_EAST) / predict_EAST;

Here are some macro processing fundamentals that will bear more study and reading.
1) You cannot use a macro variable created with CALL SYMPUT in the same program in which the macro variable is created. A step boundary must occur before you reference the macro variable.

2) Also, when you use CALL EXECUTE, any statements that you generate will be submitted AFTER the step boundary for the program in which the CALL EXECUTE string or macro call is created. Therefore, any code you submit or macro program you invoke, must generate syntactically correct SAS code. An assignment statement cannot "live" outside of a DATA step program -- so therefore, your macro would need to generate a syntactically correct SAS program.

In comparison, my macro program creates 1 assignment statement WITHIN a single DATA step program when the passed parameter &SUFF is EAST and a different assignment statement when the passed parameter &SUFF is PRODUCT. Those assignment statements result in the creation of NEWVAR_EAST and PROFIT_PRODUCT variables in the new dataset.

Studying a bit more on how the SAS Macro Facility operates may help you redesign your process. However, to get the most help from the forum, you can explain a bit more about what you want to achieve and keep all your posts in one place so folks don't have to bounce around to follow the thread.

Ask a Question
Discussion stats
  • 2 replies
  • 3 in conversation