Procedure for Stamping Source File Information on SAS Output Elizabeth Molloy & Breda O'Connor, ICON Clinical Research ABSTRACT In the course of producing a report for a clinical trial numerous drafts may be produced and tables and listings may be generated using several different versions of the data and the programs. In order to keep track of the various versions it is advisable to record, at least, the source information relating to the data sets and programs used. This information should preferably appear on the hard copy of the output. While this information may be easily obtained with certain operating systems it is more difficult with SAS for Windows on a PC LAN operating system. Therefore a procedure for printing any or all of the following information on a table or data listing has been devised. Filename, filepath and version date of the program used to produce the output. Version date and location of the data sets used to produce the output. Version of SAS used and the time and date that SAS session was invoked. A userid for the individual responsible for producing the output. INTRODUCTION The filename and filepath of the current program are obtained from the appropriate SQL data view. The CALL SYSTEM command is then used to obtain the version date of the file from DOS. The creation date and location of the data sets used are obtained using the CONTENTS procedure or another SQL data view. This information along with the system time and date are manipulated and output as macro variables for use in 'title' or 'footnote' statements, using the CALL SYMPUT routine. This code may be included in other programs and used to automatically update the source file information every time the output is reproduced. PROC SQL provides the capability to retrieve information about all libraries and external files that are allocated in a session. Dictionary tables are special read-only PROC SQL objects that contain system catalogs for all SAS data sets and other SAS files. For each dictionary table, a PROC SQL view is available in the SASHELP data library. Data views can be thought of as virtual SAS data sets 1 as they do not contain actual data but describe data stored in other file structures. These PROC SQL views can be specified in other procedures and DATA steps, whereas dictionary tables are available only by using the DICTIONARY.TABLES component of the SQL procedure. The following list includes the names of some of the PROC SQL views in the SASHELP library; VCATALG, VEXTFL, VMEMBER, VOPTION, VTABLE etc. DICTIONARY.EXTFILES for example lists external files that are currently associated by filerefs with the SAS session, the corresponding SASHELP view is created using the following code proc sql; create view sashelp.vextfl as select * from dictionary.extfiles; The select statements which define each SASHELP SQL view are given on pages 290-291 of SAS Technical Report P-222. SAS PROGRAM FILE DETAILS
The following code may be used to obtain the filename, filepath & version date of the current SAS program. set sashelp.vextfl; if _n_ = 1 then do; call symput("pgmname",xpath); end; options noxwait noxsync; e call system("dir &pgmname > file.lis"); infile 'file.lis' firstobs=5; if _n_ > 1 then stop; input prefix $ suffix $ size $ date mmddyy9. time $ ; stamp = 'Program left(trim(prefix)) '.' left(trim (suffix)) ' (dated ' put (date,ddmmyy8.) ) ; call symput ('foot',stamp); footnote1 "&foot"; c The filepath is read as the first i.e. latest record from the sashelp view. Note the positioning of this code in the program is important. because the last entry in this view is affected by code inserted into the pgm window as an include statement or programs opened into other windows including notepad If this code is inserted into the program as an include statement then _n_ = 2 selects the path for the original program. d The XWAIT and XSYNC options control what happens when the SAS System exits to DOS. The NOXWAIT option means that the SAS System does not wait for a user response before closing the DOS window. The NOXSYNC options means that control c d f g is returned immediately to the SAS System and the command continues executing without interfering with the SAS session. e The CALL SYSTEM routine is similar to the X command; however, the CALL SYSTEM routine is callable and can therefore be executed conditionally. The file.lis text file created in the working directory has the following format; 00001 00002 Volume in drive H is SYS 00003 Directory of H:\MOLLOYB\SAS 00004 00005 SQL SAS 2,154 03-18-97 5:11p 00006 1 file(s) 2,154 bytes 00007 0 dir(s) 1,560,903,680 bytes free f The fifth line of this text file provides the required file details which are read in with a list style input statement. The layout of this text file, e.g. the date format may be host specific and should be checked. g The date is written in American format and is read in using the mmddyyw. informat so as to be stored as a SAS date. SAS DATASET DETAILS Details of data sets in data libraries associated with the SAS session may be obtained using the SASHELP.VTABLE data view, or also by using the CONTENTS procedure. Several permanent data sets may be used in any one program. The creation date for each of these could be obtained but this would require a significant amount of explicit programming within each program. An alternative would be to chose one data set which is significant to each program and is most likely to be updated when new data is obtained. The name of
this data set is then assigned as the keydata macro variable and the creation date for this data set obtained using the following code. %let keydata = LIBRAW.DEMO; proc contents noprint data=&keydata out=temp(keep=crdate); data temp; set temp; if _n_ = 1; OR set sashelp.vtable; where libname = put(scan("&keydata",1),$8.) and memname = put(scan("&keydata",2),$8.); footnote2 "Data sets created &crdate"; SAS SESSION DETAILS When SAS is invoked a set of automatic macro variables is created, these include; SYSDATE - Date when job or session started execution. SYSDAY - The current day of the week as a word. SYSTIME - Returns the time SAS was invoked or a batch job started execution. SYSVER - Returns the version of the SAS System being used e.g. 6.11. These automatic system macro variables can be manipulated as required and included in the output. tdate = put("&sysdate"d,worddate12.); call symput ('newdate', tdate); title "&newdate"; PROGRAM USERID In order to provide an audit trail for SAS jobs it is important to try and identify the SAS user who has been involved in running the program, however there is no straightforward way to find this information from within the SAS system. The following example makes use of the programmer s personal directory on the network. In our company this home directory is assigned as the working directory for SAS so that personal SAS profiles can be saved there and so as to avoid conflicts when multiple users invoke SAS. This code uses the PROC SQL function to read part of the SASUSER directory path into a macro variable which denotes the userid. The scan function selects the second word in the filepath, using the backslash as the word delimiter. This information could also been obtained from the SASHELP. VMEMBERS SQL view. proc sql; select scan(path,2,'\') into :userid from dictionary.members where libname = 'SASUSER' and memname = 'PROFILE'; quit; Obviously this method of obtaining a userid is host specific and depends on the network set-up etc. Alternatives include obtaining the login ID of a user as a DOS environment variable or by accessing routines that reside inside network specific dynamic link libraries (DLLs). These methods are described by David Barron 2 in the SAS Observations magazine.
PROGRAM EXAMPLE The program presented in attachment 1 combines all of the code modules outlined above and builds a set of footnotes and titles which illustrate how a SAS table can be stamped with the source file information. CONCLUSION Obtaining information on which program was used to produce a certain table or graph, when it was run and by whom, is vital to keeping track of different versions of SAS output. While all of these items could be entered manually into a program, it is likely that they will not always be correctly updated when programs are being re-run or copied. By manipulating information that is readily available in SQL data views and automatic system macro variables the important source file information can be obtained automatically every time a program is run. Printing this information on SAS output, using the type of code described above, enhances the output and facilitates version control and auditing procedures. Author contact : Elizabeth Molloy ICON Clinical Research South County Business Park Leopardstown Dublin 18 Ireland. e-mail : molloyb@iconirl.com SAS is the registered trademark of SAS Institute Inc., Cary, NC. 1 Boling J.C., SAS Data Views : A Virtual View of Data, SAS Observations, 3 rd Quarter 1993. 2 Barron David, Input/Output, 57-59, SAS Observations, 3 rd Quarter 1996. Attachment 1 /* Program to illustrate the stamping of Source File Information on SAS Output. This program is save in the c:\temp\progs directory*/ options ls=80 ps=50 nodate nonumber nocenter; title ' '; footnote ' '; /* To create two datasets to be put into a permenant library */
libname libraw 'c:\temp\datasets'; %let keydata = LIBRAW.DEMO; data libraw.name; input number name $ sex $; cards; 1 ALFRED M 2 ALICE F 3 BARBARA F 4 CAROL F 5 HENRY M 6 JAMES M 7 JANE F 8 JANET F 9 JEFFREY M 10 JOHN M data libraw.demo; input number age height weight; cards; 1 14 69.0 112.5 2 13 56.5 84.0 3 13 65.3 98.0 4 14 62.8 102.5 5 14 63.5 102.5 6 12 57.3 83.0 7 12 59.8 84.5 8 15 62.5 112.5 9 13 62.5 84.0 10 12 59.0 99.5 /* This section of code defines the automatically updated footnotes */ set sashelp.vextfl; if _n_ = 1 then do; call symput("pgmname",xpath); end; options noxwait noxsync; call system("dir &pgmname > file.lis"); infile 'file.lis' firstobs=5; if _n_ > 1 then stop; /* This code could also be inserted as an include statement */ title " Listing of Demographic Details"; footnote1 "&foot" ; footnote2 "run by &userid with SAS &sysver on &sysdate"; footnote3 "using Data sets created &crdate"; data all noobs; merge libraw.name libraw.demo; by number; proc print noobs; dm pgm 'pgm; recall; file "c:\temp\progs\stamplis.sas"'; SAS Output Listing of Demographic Details OBS NUMBER NAME SEX AGE HEIGHT WEIGHT 1 1 ALFRED M 14 69.0 112.5 2 2 ALICE F 13 56.5 84.0 3 3 BARBARA F 13 65.3 98.0 4 4 CAROL F 14 62.8 102.5 5 5 HENRY M 14 63.5 102.5 6 6 JAMES M 12 57.3 83.0 7 7 JANE F 12 59.8 84.5 8 8 JANET F 15 62.5 112.5 9 9 JEFFREY M 13 62.5 84.0 10 10 JOHN M 12 59.0 99.5 input prefix $ suffix $ size $ date mmddyy9. time $ ; stamp = 'Program ' left(trim(prefix)) '.' left(trim (suffix)) ' (dated ' put (date,ddmmyy8.) ')'; call symput ('foot',stamp); Program STAMPLIS.SAS (dated 26/03/97) run by MOLLOYB with SAS 6.11 on 26MAR97 using Data sets created 26MAR97:17:41:54 proc contents noprint data=&keydata out=temp(keep=crdate); data temp; set temp; if _n_ = 1; proc sql noprint; select put(scan(path,2,'\'),$8.) into :userid from dictionary.members where libname = 'SASUSER' and memname = 'PROFILE'; quit;