08-06-2014 01:19 PM
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:
LIBNAME X "&UDIR\SAS TABLES\201408\&RUNDATE";
What I would like:
LIBNAME X "&UDIR\SAS TABLES\201408\&RUNDATE"
What I currently have to do:
LIBNAME X "&UDIR\SAS TABLES\201408\05AUG"
08-06-2014 01:38 PM
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.
/* at end of program 1 */
file 'my file to hold the date value.txt";
/* at beginning of program 2 */
filename datex 'my file to hold the date value.txt";
08-06-2014 01:46 PM
If it's feasible, you could always link the two programs. For example, the last statement in Program 1 could be:
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.
08-06-2014 03:46 PM
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.));
08-06-2014 05:34 PM
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.
insert into libref.lastrun (datetime,pathname)
proc sql noprint ;
select quote(trim(pathname)) into athname
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.
08-07-2014 09:05 AM
I will use OS command ( X statement ) to get these the newest table name and use them in the new code .
08-07-2014 09:31 AM
You could also keep a log file in your root directory:
LIBNAME X "&UDIR\SAS TABLES";
attrib last_run_date format=date9.
Then each time you run your program, at the end have a brief step to insert the new value:
insert into x.log
If you want the latest dated one then:
libname last "%sysfunc(pathname(x))\&floc.";
08-10-2014 03:46 AM
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
create a library based on today
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 ;-)
08-10-2014 04:50 AM
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.