BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
BobyGadu
Calcite | Level 5

 

 

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);

 

1 ACCEPTED SOLUTION

Accepted Solutions
PGStats
Opal | Level 21

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

6 REPLIES 6
PGStats
Opal | Level 21

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
BobyGadu
Calcite | Level 5
Awesome thank you
Astounding
PROC Star

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.

Reeza
Super User

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.  

Tom
Super User Tom
Super User

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;
BobyGadu
Calcite | Level 5
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

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

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