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!
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;
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.
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;
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.
I will use OS command ( X statement ) to get these the newest table name and use them in the new code .
Xia Keshan
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.";
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
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.
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.
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.