BookmarkSubscribeRSS Feed
mcrum1
Calcite | Level 5

Hello! I’m still pretty new to SAS. Please bear with me while I ask my question. I created a directory with my libname statement that creates a daily folder named after the date it was created. If I wanted to reference those tables in the last folder created in another program how would I do that? Currently I run the programs on separate days and I’m having to manually change the libname statement to reference the last date ran. I would like to automate it if at all possible.

UDIR= My user directory

Rundate = 06AUG

Program 1 that creates the directory:

     options dlcreatedir;

     LIBNAME X "&UDIR\SAS TABLES\201408\&RUNDATE";

Program 2:

                What I would like:

     LIBNAME X "&UDIR\SAS TABLES\201408\&RUNDATE"

                What I currently have to do:

     LIBNAME X "&UDIR\SAS TABLES\201408\05AUG"

Thanks!

8 REPLIES 8
jwillis
Quartz | Level 8

I wrote my rundate out to a txt file then read the text file into the second program.  I made the value in the text file a macro variable in the second program.  I am certain that SAS experts have more novel solutions.

(not tested)

/* at end of program 1 */

data _null_;

    file 'my file to hold the date value.txt";

    put "&rundate.";

run;

/* at beginning of program 2 */

filename datex 'my file to hold the date value.txt";

data _null_;

  infile datex.....

  input.........

  call symput........

run;

Astounding
PROC Star

If it's feasible, you could always link the two programs.  For example, the last statement in Program 1 could be:

%include program2.sas;

But I know there are posters here who can solve this.  There definitely are ways to say, "Create a list of all subfolder names, and read that into a DATA step."  Then have the DATA step find the largest value.  Presumably the largest value is the right one, since all your sufolders would belong to the same month.

ballardw
Super User

Does this help? Given your input the macro variable lastdate gets the previous day and month. This will cross months and years.

%let Rundate = 06AUG;

%let Lastdate= %sysfunc(inputn(&rundate.2014,date9.));

%let lastdate= %sysfunc(putn(&lastdate-1,date5.));

%put &lastdate;

Tom
Super User Tom
Super User

1) If they both run on the same day then program 2 can use the same logic to set RUNDATE as program 1.

2) If program 2 always runs the day after Program 1 then you can calculate yesterday's date from today's date: 

%let prevrun=%sysfunc(putn("&sysdate9"d -1,date5.));

LIBNAME X "&UDIR\SAS TABLES\201408\&prevrun";

3) you could store the last run date and path used into a table and pull it out again in program 2.

Program1:

proc sql;

  insert into libref.lastrun (datetime,pathname)

  values (%sysfunc(datetime()),"%sysfunc(pathname(x))")

  ;

quit;

Program 2:

proc sql noprint ;

  select quote(trim(pathname)) into :pathname

  from libref.lastrun

  where datetime=max(datetime)

;

quit;

libname x &pathname ;

4) You could read the directories and figure out which is the last one from the name.  But for this to work you really should convert from using 05AUG to something more complete.  I like to use dates in YYYYMMDD format for date stamps in file names because then they sort naturally.

Ksharp
Super User

I will use OS command ( X statement ) to get these the newest table name and use them in the new code .

Xia Keshan

RW9
Diamond | Level 26 RW9
Diamond | Level 26

You could also keep a log file in your root directory:

LIBNAME X "&UDIR\SAS TABLES";

data x.log;

     attrib last_run_date format=date9.

               folder_location format=$2000.;

     last_run_date='06JUL2014'd;

     folder_loction="\06JUL";

     output;

run;

Then each time you run your program, at the end have a brief step to insert the new value:

proc sql;

     insert into x.log

     set last_run_date=today(),

             folder_location="\"||substr(put(today(),date9.),1,5);

quit;

If you want the latest dated one then:

proc sql;

     select folder_location

     into   :floc

     from     x.log

     having max(last_run_date);

quit;

libname last "%sysfunc(pathname(x))\&floc.";

              

Peter_C
Rhodochrosite | Level 12

Interesting challenge

Sometimes automating our SAS environment takes a bit longer than expected. One example might be the time it takes for the DOPEN and FOPEN functions to deliver the latest file or directory name in a path when compared with checking existence of a file and a second.

Here is an approach using a few small macros

1 NEW_DAY_LIB

create a library based on today

2 PRIOR_LIB

if prior_L global symbol doesn't exists, create it as today

Try assigning a library for &prior_L

if it fails (&syslibrc=0) subtract 1 from prior_L and try assignment again

When assignment succeeds (&syslibrc=1) exit the macro

Interesting challenge in PRIOR_LIB to code for handling a month-end with  a new parent folder when today is 1st September

Supporting NEW_LIB is the function dcreate(). It can be wrapped within %sysfunc(). It enables sas users of enterprise guide sharing a server to create folders witbout needing X statements or PIPE  filenames.

It might be interesting and appear simpler to make PRIOR_LIB  recursive, but the depth limit would probably be breached if the user came back from a 10 day holiday 😉

interesting challenge

jakarman
Barite | Level 11

This is some question more generic as just SAS. It is about running business applications infrastructure supporting different stages of DTAP (Develop Test User-Acceptance Production) and using a business-reference date.
You can see those settings as some generic set to be set up at startup of the business-processing for all kind of processes.

For production business-systems often the today() setting is used. While in testing environments you must have a fixed setting to be able to do regression testing. with fixed test-datasets during a verification.

Within that kind of processed a loop of recurrent daily processes can exist with a at that moment becoming point of date.

I believe this is what you are doing.

Putting is in one program and do a %include of that in every other program belonging will solve the redundancy. 

Setting program. "bu_001_refdate.sas"

.   %let  UDIR= My user directory\;

.   %let  Uxlib=&UDIR.SAS TABLES\201408\;

.   %let Rundate = 06AUG;

.

options dlcreatedir;

. LIBNAME X "&Uxlib.&RUNDATE";

All of your other programs starting with:

  %include "&ugenset.bu_001_refdate.sas" ;

This is a start as you see to eliminate all kind of physical namings from the coding.
By that the code will be able to run on all type of machinetypes with little modifications

There must be a last step/process being run that validates all processing has ended successfully and a next iteration / new date / can be started. That is a nice trigger for a sas-job for creating/writing out the sas-source: bu_001_refdate.sas

The ugenset macrovariabel is something to set in a startup/autoexec as there must be a location where your code is to be found.
The %include is similar of calling a sub-program as used in many other program languages for modular constructs.

---->-- ja karman --<-----

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 8 replies
  • 1579 views
  • 1 like
  • 9 in conversation