DATA Step, Macro, Functions and more

macro resolving

Accepted Solution Solved
Reply
Contributor
Posts: 30
Accepted Solution

macro resolving

 

 

Why my macro is not resolving

 

 

%Macro georg(srv_st_dt,srv_en_dt,pst_dt1,pst_dt2 );

 

/*%let pst_dt1 =01/01/2009;*/

%put &pst_dt1;

data _null_ ;

%put &pst_dt1;

call symput ('pst1', put(input(&pst_dt1,mmddyy10.),date9.));

*call symput ('pst1', put(input("&pst_dt1",mmddyy10.),date9.));

call symput ('pst2',put(input("&pst_dt2",mmddyy10.),date9.));

call symput ('srv_st_dt',put(input("&srv_st",mmddyy10.),date9.));

call symput ('srv_en_dt',put(input("&srv_en",mmddyy10.),date9.));

run;

%put &pst1;

%mend georg;

%georg (01/01/2009 ,06/31/2009 ,01/01/2009 ,06/30/2009);

 


Accepted Solutions
Solution
‎07-24-2016 11:44 AM
Respected Advisor
Posts: 4,919

Re: macro resolving

I guess you want to do something like this:

 

%Macro georg(srv_st,srv_en,pst_dt1,pst_dt2 );
%global pst1 pst2 srv_st_dt srv_en_dt; 
data _null_ ;
call symput ('pst1', put(input("&pst_dt1", mmddyy10.),date9.));
call symput ('pst2', put(input("&pst_dt2", mmddyy10.),date9.));
call symput ('srv_st_dt', put(input("&srv_st", mmddyy10.),date9.));
call symput ('srv_en_dt', put(input("&srv_en", mmddyy10.),date9.));
run;
%mend georg;

%georg (01/01/2009, 06/30/2009, 01/01/2009, 06/30/2009);

%put &pst1;
%put &pst2;
%put &srv_st_dt;
%put &srv_en_dt;

The complexity of macro variable scope rules is just another reason why I stay away from macro programming.  

PG

View solution in original post


All Replies
Solution
‎07-24-2016 11:44 AM
Respected Advisor
Posts: 4,919

Re: macro resolving

I guess you want to do something like this:

 

%Macro georg(srv_st,srv_en,pst_dt1,pst_dt2 );
%global pst1 pst2 srv_st_dt srv_en_dt; 
data _null_ ;
call symput ('pst1', put(input("&pst_dt1", mmddyy10.),date9.));
call symput ('pst2', put(input("&pst_dt2", mmddyy10.),date9.));
call symput ('srv_st_dt', put(input("&srv_st", mmddyy10.),date9.));
call symput ('srv_en_dt', put(input("&srv_en", mmddyy10.),date9.));
run;
%mend georg;

%georg (01/01/2009, 06/30/2009, 01/01/2009, 06/30/2009);

%put &pst1;
%put &pst2;
%put &srv_st_dt;
%put &srv_en_dt;

The complexity of macro variable scope rules is just another reason why I stay away from macro programming.  

PG
Contributor
Posts: 30

Re: macro resolving

Awesome thank you
Super User
Posts: 5,497

Re: macro resolving

[ Edited ]

Your commented out line has the right idea:

 

 

*call symput ('pst1', put(input("&pst_dt1",mmddyy10.),date9.));

 

Without the quotes means something entirely different:

 

call symput ('pst1', put(input(&pst_dt1,mmddyy10.),date9.));

 

In that statement, 01/01/2009 means 1 divided by 1 divided by 2009.  Then SAS has to take that result and convert it to character, before applying the DATE9 informat.

 

It would be more helpful in the future if you were to actually show what results you are getting.

Super User
Posts: 19,770

Re: macro resolving

Use CALL SYMPUTX. 

The third parameter allows you to specify local or global. 

 

Currently your creating local macro variables that don't exist outside your macro. Creating global macro variables mean they exist for your entire program.  

Super User
Super User
Posts: 7,039

Re: macro resolving

Macros  are RUN or CALLED or EXECUTED.  Macro VARIABLES are RESOLVED.

 

Are you worried that your macro variables are not getting set right?  

Or are you worried that they are not available after the macro itself has finished running?

 

To see if your macro CALL is RUNNING you can turn on the MPRINT option.  You will lines like this in your SAS log.

01/01/2009
MPRINT(GEORG):   data _null_ ;
01/01/2009
MPRINT(GEORG):   call symput ('pst1', put(input(01/01/2009,mmddyy10.),date9.));
MPRINT(GEORG):   *call symput ('pst1', put(input("&pst_dt1",mmddyy10.),date9.));
MPRINT(GEORG):   call symput ('pst2',put(input("06/30/2009",mmddyy10.),date9.));
WARNING: Apparent symbolic reference SRV_ST not resolved.
MPRINT(GEORG):   call symput ('srv_st_dt',put(input("&srv_st",mmddyy10.),date9.));
WARNING: Apparent symbolic reference SRV_EN not resolved.
MPRINT(GEORG):   call symput ('srv_en_dt',put(input("&srv_en",mmddyy10.),date9.));
MPRINT(GEORG):   run;

NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
      1:6
NOTE: Invalid argument to function INPUT at line 3 column 27.
NOTE: Invalid argument to function INPUT at line 3 column 218.
NOTE: Invalid argument to function INPUT at line 4 column 31.
_ERROR_=1 _N_=1
NOTE: Mathematical operations could not be performed at the following places. The results of the operations
      have been set to missing values.
      Each place is given by: (Number of times) at (Line):(Column).
      1 at 3:27    1 at 3:218   1 at 4:31
NOTE: DATA statement used (Total process time):
      real time           0.04 seconds
      cpu time            0.00 seconds

Are there particular parts of that they you want to work differently?

If so you need to explain what you want.

 

There are a numer of issues in your code.

call symput ('pst1', put(input(&pst_dt1,mmddyy10.),date9.));

The first CALL SYMPUT() call is using the macro parmeter PDT_DT1 as if it contained a string literal or the name of character variable.  But you past in just the bare text  01/01/1990. SAS will see that as a numeric equation to be evaluated and then converted to a string for the INPUT() function to operate on.

The second CALL SYMPUT() call fixes that issue by enclosing the macro variable's value inside of double quotes so that it will look like a string literal to the SAS compiler.

 

call symput ('srv_st_dt',put(input("&srv_st",mmddyy10.),date9.));
call symput ('srv_en_dt',put(input("&srv_en",mmddyy10.),date9.));

The third and fouth CALL SYMPUT() calls are referencing a macro variables, SRV_ST and SRV_EN, that are not defined in the piece of code you posted. It might work ok if the variables exist and have a value that looks like a valid MM/DD/YYYY value.

 

All four of the CALL SYMPUT() calls are assigning values to macro variables that you have not defined anywhere in the code you posted.  If they exist before the macro is called then they will have their values replaced. Otherwise they will be created as local to the macro GEORG and disappear when it ends.  If you want to use the value after GEORG finishes then you should either just create them first.

%let pst1=;
%let pst2=;
%let srv_st_dt=;
%let srv_en_dt=;
%georg (01/01/2009 ,06/31/2009 ,01/01/2009 ,06/30/2009);

Or modify the macro to make sure they exist before writing to them.  Note you could use CALL SYMPUTX() and force them into the GLOBAL symbol table, but that will fail if they already exist inside some other macro that is call GEORG as a submacro.

%macro georg(srv_st_dt,srv_en_dt,pst_dt1,pst_dt2 );
%if not %symexist(pst1) %then %global pst1;
%if not %symexist(pst2) %then %global pst2;
%if not %symexist(srv_st_dt) %then %global srv_st_dt;
%if not %symexist(srv_en_dt) %then %global srv_en_dt;

...

%mend georg;
Contributor
Posts: 30

Re: macro resolving

Macro date passed as string that is the reason why I have one in quotes and other not but it is the scope of the variable restricted
☑ This topic is solved.

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

Discussion stats
  • 6 replies
  • 300 views
  • 0 likes
  • 5 in conversation