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

Hello, 

 

I have the following SAS code:

 

LIBNAME TESTS '/disk1/sand/SAS/workdir' ;

options mprint symbolgen;

data TESTS.SYMPUT_001_DS0;
call symputx('curr_dt',put(today(),yymmddn8.),'G');
call symput('curr_date', put('&&curr_dt&',8.));
call symputx('prev_dt',put(today()-1,yymmddn8.),'G');
call symput('prev_date', put('&&prev_dt&',8.));

curr_dt = put(today(),yymmddn8.);
curr_date = put('&&curr_dt&',8.);
prev_dt = put(today() - 1,yymmddn8.);
prev_date = put('&&prev_dt&',8.);
run;

%put &=curr_dt ;
%put &=curr_date ;
%put &=prev_date ;
%put &=prev_dt ;

data TESTS.SYMPUT_001_DS1;
set TESTS.SYMPUT_001_DS0;
length dt_num 8;
length dt_str $ 10;

dt_num = &curr_dt;
dt_str = '&&curr_date&.';
output;

dt_num = &prev_dt;
dt_str = '&&prev_date&.';
output;

if &curr_dt > &prev_dt then output;
run;

data TESTS.SYMPUT_001_DS2;
set TESTS.SYMPUT_001_DS1;
where dt_num = &curr_dt;
run;

 

 

When I run it using command line SAS (9.4) on linux, I get the following errors:

WARNING: Apparent symbolic reference CURR_D not resolved.

WARNING: Apparent symbolic reference PREV_D not resolved

 

Does anyone know what is wrong?

 

Thank you,
Peter.

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
dualice
Fluorite | Level 6

Thank you for your responses. The fixes was exactly that - separating the single statements into two. the changed code, which now does not throw that warning is this:

 

LIBNAME TESTS '/disk1/sand/SAS/workdir' ;

options mprint symbolgen;

data TESTS.SYMPUT_001_DS0;
call symputx('curr_dt',put(today(),yymmddn8.),'G');
call symputx('prev_dt',put(today()-1,yymmddn8.),'G');

curr_dt = put(today(),yymmddn8.);
prev_dt = put(today() - 1,yymmddn8.);
run;

data TESTS.SYMPUT_001_DS1;
set TESTS.SYMPUT_001_DS0;
call symput('curr_date', put("&curr_dt",8.));
call symput('prev_date', put("&prev_dt",8.));

curr_date = put("&curr_dt",8.);
prev_date = put("&prev_dt",8.);
run;

%put &=curr_dt ;
%put &=curr_date ;
%put &=prev_date ;
%put &=prev_dt ;

data TESTS.SYMPUT_001_DS2;
set TESTS.SYMPUT_001_DS1;
length dt_num 8;
length dt_str $ 10;

dt_num = &curr_dt;
dt_str = "&curr_date";
output;

dt_num = &prev_dt;
dt_str = "&prev_date";
output;

if &curr_dt > &prev_dt then output;
run;

data TESTS.SYMPUT_001_DS3;
set TESTS.SYMPUT_001_DS2;
where dt_num = &curr_dt;
run;

View solution in original post

11 REPLIES 11
ballardw
Super User

First thing is that macro variables will not resolve inside single quotes so none of these Put resolve anything.

call symput('curr_date', put('&&curr_dt&',8.));
call symput('prev_date', put('&&prev_dt&',8.));
  

 Second is that you cannot use the macro variables in the same data step that creates then as you are attempting to do so they aren't defined in the first data step.

 

Somewhat of an example:

data example;
call symputx('curr_dt',put(today(),yymmddn8.),'G');
run;

%put Curr_dt is: &curr_dt.;
/* resolves to  Curr_dt is: 20211213*/

data junk;
  call symput('curr_date', put("&&curr_dt&",8.));
run;
%put Curr_date is: &curr_date.;
/*Resolves to Curr_date is: 20211213*/

Your code is a convoluted way to make a second variable with the same value as currently attempted.

BTW, if you intend to compare these to SAS date values you may be disappointed.

 

Note: Your warnings would not come from the code shown. There is no place you use macro variables CURR_D or PREV_D, you use CURR_DT and PREV_DT. So those warnings come from different code.

 


@dualice wrote:

Hello, 

 

I have the following SAS code:

 

LIBNAME TESTS '/disk1/sand/SAS/workdir' ;

options mprint symbolgen;

data TESTS.SYMPUT_001_DS0;
call symputx('curr_dt',put(today(),yymmddn8.),'G');
call symput('curr_date', put('&&curr_dt&',8.));
call symputx('prev_dt',put(today()-1,yymmddn8.),'G');
call symput('prev_date', put('&&prev_dt&',8.));

curr_dt = put(today(),yymmddn8.);
curr_date = put('&&curr_dt&',8.);
prev_dt = put(today() - 1,yymmddn8.);
prev_date = put('&&prev_dt&',8.);
run;

%put &=curr_dt ;
%put &=curr_date ;
%put &=prev_date ;
%put &=prev_dt ;

data TESTS.SYMPUT_001_DS1;
set TESTS.SYMPUT_001_DS0;
length dt_num 8;
length dt_str $ 10;

dt_num = &curr_dt;
dt_str = '&&curr_date&.';
output;

dt_num = &prev_dt;
dt_str = '&&prev_date&.';
output;

if &curr_dt > &prev_dt then output;
run;

data TESTS.SYMPUT_001_DS2;
set TESTS.SYMPUT_001_DS1;
where dt_num = &curr_dt;
run;

 

 

When I run it using command line SAS (9.4) on linux, I get the following errors:

WARNING: Apparent symbolic reference CURR_D not resolved.

WARNING: Apparent symbolic reference PREV_D not resolved

 

Does anyone know what is wrong?

 

Thank you,
Peter.

 

 


 

dualice
Fluorite | Level 6

Thanks for your help.

 

Here is the log:

SYMBOLGEN: && resolves to &.
WARNING: Apparent symbolic reference CURR_DT not resolved.
9 call symputx('prev_dt',put(today()-1,yymmddn8.),'G');
2 The SAS System 17:08 Monday, December 13, 2021

10 call symput('prev_date', put("&&prev_dt&",8.));
SYMBOLGEN: && resolves to &.
WARNING: Apparent symbolic reference PREV_DT not resolved.
11
12 curr_dt = put(today(),yymmddn8.);
13 curr_date = put("&&curr_dt&",8.);
SYMBOLGEN: && resolves to &.
WARNING: Apparent symbolic reference CURR_DT not resolved.
14 prev_dt = put(today() - 1,yymmddn8.);
15 prev_date = put("&&prev_dt&",8.);
SYMBOLGEN: && resolves to &.
WARNING: Apparent symbolic reference PREV_DT not resolved.
16 run;

NOTE: The data set TESTS.SYMPUT_001_DS0 has 1 observations and 4 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds


SYMBOLGEN: Macro variable CURR_DT resolves to 20211213
17
18 %put &=curr_dt ;
CURR_DT=20211213
19 %put &=curr_date ;
SYMBOLGEN: Macro variable CURR_DATE resolves to &curr_dt
SYMBOLGEN: Macro variable CURR_DT resolves to 20211213
CURR_DATE=20211213
20 %put &=prev_date ;
SYMBOLGEN: Macro variable PREV_DATE resolves to &prev_dt
SYMBOLGEN: Macro variable PREV_DT resolves to 20211212
PREV_DATE=20211212
21 %put &=prev_dt ;
SYMBOLGEN: Macro variable PREV_DT resolves to 20211212
PREV_DT=20211212

 

 

I am thrown off (well, by a a lot things, but specifically) by the upper/lower case in the WARNING while the code has lower case.

 

Tom
Super User Tom
Super User

Error messages in a log normally come after the code that caused them. So not including the lines from the SAS log that come before the error message makes it impossible to see what lines of code caused the error.

 

SAS names are case insensitive. FRED and fred refer the same variable/dataset/libref/fileref/format/informat.

 

Let's look carefully at your first data step.

 

data TESTS.SYMPUT_001_DS0;
  call symputx('curr_dt',put(today(),yymmddn8.),'G');
  call symput('curr_date', put('&&curr_dt&',8.));
  call symputx('prev_dt',put(today()-1,yymmddn8.),'G');
  call symput('prev_date', put('&&prev_dt&',8.));

  curr_dt = put(today(),yymmddn8.);
  curr_date = put('&&curr_dt&',8.);
  prev_dt = put(today() - 1,yymmddn8.);
  prev_date = put('&&prev_dt&',8.);
run;

The first statement seems kind of normal:

  call symputx('curr_dt',put(today(),yymmddn8.),'G');

will create a global macro variable named CURR_DT that is set to the series of digits like 20211213.

 

The second one is really confused.

  call symput('curr_date', put('&&curr_dt&',8.));

Because you are using single quotes instead of double quotes the macro processor will ignore the & macro triggers.  So you are calling the PUT() function and passing it a 10 character string.  You also give the PUT() function a numeric format.  But SAS is forgiving of type miss matches in a lot of places so it decides that you must have meant to use the character format $8. instead.  This means that the macro variable CURR_DATE is going to be set to the first 8 of those 10 character. 

&&curr_d

What is it that you WANT to do?

 

Perhaps you want to make one macro variable with today's date and another with a string of digits in YYYYMMDD style that you could use to build a filename?

data want ;
  curr_dt = today();
  prev_dt = curr_dt - 1;
  format curr_dt prev_dt date9.;

  call symputx('curr_dt',curr_dt,'G');
  call symputx('prev_dt',prev_dt,'G');

  call symputx('curr_yyyymmdd',put(curr_dt,yymmddn8.),'G');
  call symputx('prev_yyyymmdd',put(prev_dt,yymmddn8.),'G');
run;

Results:

1343  %put &=curr_dt &=curr_yyyymmdd;
CURR_DT=22627 CURR_YYYYMMDD=20211213
1344  %put &=prev_dt &=prev_yyyymmdd;
PREV_DT=22626 PREV_YYYYMMDD=20211212

Dataset:

Obs      curr_dt      prev_dt

 1     13DEC2021    12DEC2021

You can now use those macro variables:

data asof_&curr_yyyymmdd ;
  set have;
  where datevar <= &curr_dt;
run;

 

dualice
Fluorite | Level 6

Hello,

 

Thank you for replying. The single quotes was the results of me flailing to figure out something that would work. So are the double &.

 

Here is the original code that throws the same warnings:

 

LIBNAME TESTS '/disk1/sand/SAS/workdir' ;

options mprint symbolgen;

data TESTS.SYMPUT_001_DS0;
    call symput('curr_dt',put(today(),yymmddn8.));
    call symput('curr_date', put("&curr_dt&",8.));
    call symput('prev_dt',put(today()-1,yymmddn8.));
    call symput('prev_date', put("&prev_dt&",8.));

    curr_dt     = put(today(),yymmddn8.);
    curr_date   = put("&curr_dt&",8.);
    prev_dt     = put(today() - 1,yymmddn8.);
    prev_date   = put("&prev_dt&",8.);
run;

%put &=curr_dt   ;
%put &=curr_date ;
%put &=prev_date ;
%put &=prev_dt   ;

data TESTS.SYMPUT_001_DS1;
    set TESTS.SYMPUT_001_DS0;
    length dt_num      8;
    length dt_str   $ 10;

    dt_num = &curr_dt;
    dt_str = '&curr_date&.';
    output;

    dt_num = &prev_dt;
    dt_str = '&prev_date&.';
    output;

    if &curr_dt > &prev_dt then output;
run;

data TESTS.SYMPUT_001_DS2;
    set TESTS.SYMPUT_001_DS1;
    where dt_num = &curr_dt;
run;

 

Tom
Super User Tom
Super User

Please explain what you are trying to do.

 

You did not correct the use of a numeric format when trying to PUT() a character string.  Do you want to use a character format? Or did you want to use PUT() to operate on a numeric value?  If the later what numeric value?

 

You did not correct trying to use a macro variable to generate code before you have run any code to create it.

dualice
Fluorite | Level 6
Sorry, yes. I want to use a character format.
Tom
Super User Tom
Super User

But WHAT is the code trying to do?

What is the purpose of the macro variables? How will they be used? What is the purpose of the dataset the first data step is generating? How will it be used?

 

For example why do want to make macro variable that contains the string 20131213?  You cannot use it as a date.  A number that large would represent a date way into the future.  You could use it create a TITLE statement or possibly as part of a filename.  But then why not use a more human readable form like 2013-12-13 or 2013_12_13 ?

dualice
Fluorite | Level 6

I want the date format as a string for two purposes... 

1. for part of the name of a filename

2. the db I am eventually writing into contains a column that is a string that holds a date in that format. 

 

all this aside, I don't understand why that warning is happening and how to fix the code so that it works. 

Tom
Super User Tom
Super User

@dualice wrote:

I want the date format as a string for two purposes... 

1. for part of the name of a filename

2. the db I am eventually writing into contains a column that is a string that holds a date in that format. 

 

all this aside, I don't understand why that warning is happening and how to fix the code so that it works. 


I cannot figure out from this what you want. 

You want a string that has today's date that you can use to generate a filename?  How do you want to format the string?

You want to write to a database? Does that mean an external database, like Oracle or Redshift? Or a SAS dataset?

 

Here is a data step that will create two date variables and two character variables. It will also create two macro variables with strings in YYYYMMDD style.

data TESTS.SYMPUT_001_DS0;
  length curr_dt prev_dt 8 curr_dt_string prev_dt_string $8;
  curr_dt = today();
  curr_dt_string = put(curr_dt,yymmddn8.);
  prev_dt = curr_dt -1 ;
  prev_dt_string = put(prev_dt,yymmddn8.);
  format curr_dt prev_dt date9.;

  call symputx('curr_dt',curr_dt_string);
  call symputx('prev_dt',prev_dt_string);
run;

%put CURR_DT = "&curr_dt";
%put PREV_DT = "&prev_dt";

Resulting Dataset:

                                 curr_dt_    prev_dt_
Obs      curr_dt      prev_dt     string      string

 1     14DEC2021    13DEC2021    20211214    20211213

From SAS log

1357  %put CURR_DT = "&curr_dt";
CURR_DT = "20211214"
1358  %put PREV_DT = "&prev_dt";
PREV_DT = "20211213"

 

You can then use those macro variables to generate code.

For example let's say you want to subset some datasets name HAVE to just the observations where some character variable named DATE_STR matches the current date.

data want;
  set have;
  where date_str = "&curr_dt";
run;

Or perhaps you want to write that data to file instead of a dataset and use the string of digits when creating the filename.

data _null_;
  set have;
  where date_str = "&curr_dt";
  file "data_for_&curr_dt..txt" dsd dlm='|' ;
  put (_all_) (+0);
run;

 

dualice
Fluorite | Level 6

Thank you for your responses. The fixes was exactly that - separating the single statements into two. the changed code, which now does not throw that warning is this:

 

LIBNAME TESTS '/disk1/sand/SAS/workdir' ;

options mprint symbolgen;

data TESTS.SYMPUT_001_DS0;
call symputx('curr_dt',put(today(),yymmddn8.),'G');
call symputx('prev_dt',put(today()-1,yymmddn8.),'G');

curr_dt = put(today(),yymmddn8.);
prev_dt = put(today() - 1,yymmddn8.);
run;

data TESTS.SYMPUT_001_DS1;
set TESTS.SYMPUT_001_DS0;
call symput('curr_date', put("&curr_dt",8.));
call symput('prev_date', put("&prev_dt",8.));

curr_date = put("&curr_dt",8.);
prev_date = put("&prev_dt",8.);
run;

%put &=curr_dt ;
%put &=curr_date ;
%put &=prev_date ;
%put &=prev_dt ;

data TESTS.SYMPUT_001_DS2;
set TESTS.SYMPUT_001_DS1;
length dt_num 8;
length dt_str $ 10;

dt_num = &curr_dt;
dt_str = "&curr_date";
output;

dt_num = &prev_dt;
dt_str = "&prev_date";
output;

if &curr_dt > &prev_dt then output;
run;

data TESTS.SYMPUT_001_DS3;
set TESTS.SYMPUT_001_DS2;
where dt_num = &curr_dt;
run;

Tom
Super User Tom
Super User

I still cannot figure out what actual problem this code is supposed to be solving.

 

One warning.  It is better to calculate the date once.  If you call the DATE() function (also known as TODAY() function) multiple times and you happen to start right before midnight you might get different results.

data TESTS.SYMPUT_001_DS0;
  today=today();
  curr_dt = put(today,yymmddn8.);
  prev_dt = put(today - 1,yymmddn8.);
  call symputx('curr_dt',curr_dt,'G');
  call symputx('prev_dt',prev_dt,'G');
run;

 

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 11 replies
  • 2249 views
  • 1 like
  • 3 in conversation