Posters. Paper

Similar documents
A SAS Macro Utility to Modify and Validate RTF Outputs for Regional Analyses Jagan Mohan Achi, PPD, Austin, TX Joshua N. Winters, PPD, Rochester, NY

A Macro To Generate a Study Report Hany Aboutaleb, Biogen Idec, Cambridge, MA

Arthur L. Carpenter California Occidental Consultants, Oceanside, California

Creating Macro Calls using Proc Freq

Photos with Text Reports on the Same SAS/AF Screen

How to Implement the One-Time Methodology Mark Tabladillo, Ph.D., Atlanta, GA

How to Implement the One-Time Methodology Mark Tabladillo, Ph.D., MarkTab Consulting, Atlanta, GA Associate Faculty, University of Phoenix

Make Your Life a Little Easier: A Collection of SAS Macro Utilities. Pete Lund, Northwest Crime and Social Research, Olympia, WA

Using an ICPSR set-up file to create a SAS dataset

e. That's accomplished with:

Using Unnamed and Named Pipes

HAVE YOU EVER WISHED THAT YOU DO NOT NEED TO TYPE OR CHANGE REPORT NUMBERS AND TITLES IN YOUR SAS PROGRAMS?

Using PROC REPORT to Cross-Tabulate Multiple Response Items Patrick Thornton, SRI International, Menlo Park, CA

3. Almost always use system options options compress =yes nocenter; /* mostly use */ options ps=9999 ls=200;

Base and Advance SAS

The Output Bundle: A Solution for a Fully Documented Program Run

Implementing external file processing with no record delimiter via a metadata-driven approach

PDF Multi-Level Bookmarks via SAS

Using SAS Macro to Include Statistics Output in Clinical Trial Summary Table

SAS/AF FRAME Entries: A Hands-on Introduction

HOW TO DEVELOP A SAS/AF APPLICATION

MACROS TO REPORT MISSING DATA: AN HTML DATA COLLECTION GUIDE Patrick Thornton, University of California San Francisco

Procedure for Stamping Source File Information on SAS Output Elizabeth Molloy & Breda O'Connor, ICON Clinical Research

Program Validation: Logging the Log

SAS 101. Based on Learning SAS by Example: A Programmer s Guide Chapter 21, 22, & 23. By Tasha Chapman, Oregon Health Authority

Using SAS to Control the Post Processing of Microsoft Documents Nat Wooding, J. Sargeant Reynolds Community College, Richmond, VA

A Cross-national Comparison Using Stacked Data

Matt Downs and Heidi Christ-Schmidt Statistics Collaborative, Inc., Washington, D.C.

The Dataset Attribute Family of Classes Mark Tabladillo, Ph.D., Atlanta, GA

SAS Macro Dynamics - From Simple Basics to Powerful Invocations Rick Andrews, Office of the Actuary, CMS, Baltimore, MD

INTRODUCTION TO SAS HOW SAS WORKS READING RAW DATA INTO SAS

Jennifer Clegg and Carol Rigsbee, SAS Institute Inc., Cary, NC

Use SAS/AF, SCL and MACRO to Build User-friendly Applications on UNIX

A Macro that can Search and Replace String in your SAS Programs

LST in Comparison Sanket Kale, Parexel International Inc., Durham, NC Sajin Johnny, Parexel International Inc., Durham, NC

Your Own SAS Macros Are as Powerful as You Are Ingenious

USING DATA TO SET MACRO PARAMETERS

A Useful Macro for Converting SAS Data sets into SAS Transport Files in Electronic Submissions

Changes and Enhancements

Christopher Louden University of Texas Health Science Center at San Antonio

Using SAS/SCL to Create Flexible Programs... A Super-Sized Macro Ellen Michaliszyn, College of American Pathologists, Northfield, IL

ABSTRACT. Paper CC-031

Template Versatility Using SAS Macro Language to Generate Dynamic RTF Reports Patrick Leon, MPH

So Much Data, So Little Time: Splitting Datasets For More Efficient Run Times and Meeting FDA Submission Guidelines

Using DDE with Microsoft Excel and SAS to Collect Data from Hundreds of Users

How a Code-Checking Algorithm Can Prevent Errors

MISSOVER, TRUNCOVER, and PAD, OH MY!! or Making Sense of the INFILE and INPUT Statements. Randall Cates, MPH, Technical Training Specialist

The Proc Transpose Cookbook

BIOMETRICS INFORMATION

A Tool to Compare Different Data Transfers Jun Wang, FMD K&L, Inc., Nanjing, China

Identifying Duplicate Variables in a SAS Data Set

Getting Up to Speed with PROC REPORT Kimberly LeBouton, K.J.L. Computing, Rossmoor, CA

Generating a Detailed Table of Contents for Web-Served Output

Epidemiology Principles of Biostatistics Chapter 3. Introduction to SAS. John Koval

An Introduction to SAS Macros

Posters. Workarounds for SASWare Ballot Items Jack Hamilton, First Health, West Sacramento, California USA. Paper

Macro Architecture in Pictures Mark Tabladillo PhD, marktab Consulting, Atlanta, GA Associate Faculty, University of Phoenix

Using SAS software to fulfil an FDA request for database documentation

CHAPTER 7 Using Other SAS Software Products

Using GSUBMIT command to customize the interface in SAS Xin Wang, Fountain Medical Technology Co., ltd, Nanjing, China

Taming a Spreadsheet Importation Monster

2. Don t forget semicolons and RUN statements The two most common programming errors.

SAS CURRICULUM. BASE SAS Introduction

Electricity Forecasting Full Circle

Paper An Automated Reporting Macro to Create Cell Index An Enhanced Revisit. Shi-Tao Yeh, GlaxoSmithKline, King of Prussia, PA

Using a HASH Table to Reference Variables in an Array by Name. John Henry King, Hopper, Arkansas

\WSS95. Applications Development. Managing Longitudinal Panel Surveys Using Interactive Applications Created by SAS!Af and SASJFsp with SCL

Because We Can: Using SAS System Tools to Help Our Less Fortunate Brethren John Cohen, Advanced Data Concepts, LLC, Newark, DE

Data Tables: Highlighting Techniques Christopher A. Roper, Qualex Consulting Services, Inc.

An Introduction to SAS/SHARE, By Example

Essential ODS Techniques for Creating Reports in PDF Patrick Thornton, SRI International, Menlo Park, CA

Abstract. Background. Summary of method. Using SAS to determine file and space usage in UNIX. Title: Mike Montgomery [MIS Manager, MTN (South Africa)]

TLF Management Tools: SAS programs to help in managing large number of TLFs. Eduard Joseph Siquioco, PPD, Manila, Philippines

Paper AP14 Modifying The LogParse PassInfo Macro to Provide a Link between Product Usage in Rtrace Log and Time Used in Job Log

SD10 A SAS MACRO FOR PERFORMING BACKWARD SELECTION IN PROC SURVEYREG

Paper SE04 Dynamic SAS Programming Techniques, or How NOT to Create Job Security Steven Beakley and Suzanne McCoy

Demystifying Inherited Programs

Developing Data-Driven SAS Programs Using Proc Contents

Tales from the Help Desk 6: Solutions to Common SAS Tasks

A Macro to Keep Titles and Footnotes in One Place

Using a Control Dataset to Manage Production Compiled Macro Library Curtis E. Reid, Bureau of Labor Statistics, Washington, DC

Going Under the Hood: How Does the Macro Processor Really Work?

A Quick and Gentle Introduction to PROC SQL

Open Problem for SUAVe User Group Meeting, November 26, 2013 (UVic)

A Generic Solution to Running the SAS System on the Web Without SAS/Intrnet David L. Ward, InterNext, Inc., Somerset, NJ

Working the System: Our Best SAS Options Patrick Thornton, SRI International, Menlo Park, CA Iuliana Barbalau, Adecco, Pleasanton, CA

%Addval: A SAS Macro Which Completes the Cartesian Product of Dataset Observations for All Values of a Selected Set of Variables

SAS Data Integration Studio Take Control with Conditional & Looping Transformations

SAS Drug Development Program Portability

Automated Checking Of Multiple Files Kathyayini Tappeta, Percept Pharma Services, Bridgewater, NJ

The REPORT Procedure CHAPTER 32

Using PROC SQL to Calculate FIRSTOBS David C. Tabano, Kaiser Permanente, Denver, CO

A Tutorial on the SAS Macro Language

The Power of PROC SQL Techniques and SAS Dictionary Tables in Handling Data

Driving to Better Credit Policies : The Risk Strategy Instrument Panel

Army Hearing Evaluation Automated Registry System (HEARS) Corporate Data Reporting System -- A Customized EIS Solution

%SHOWCOMB: a macro to produce a data set with frequency of combinations of responses from multiple-response data

Using PROC SQL to Generate Shift Tables More Efficiently

Uncommon Techniques for Common Variables

Can I have the menu please?

Transcription:

Paper 212-26 Using SAS/AF to Create a SAS Program File Explorer Rob Nelson, Centers for Disease Control and Prevention, Atlanta, GA Janet Royalty, Centers for Disease Control and Prevention, Atlanta, GA Ernie Lewis, Greenville, SC ABSTRACT The SAS version 8 application presented in this poster combines the interactive features of SAS/AF with a methodology for documenting SAS programs to create a descriptive index of SAS program files within a given Windows directory. File name, creation date, and program header description are captured and displayed in an easy-to-browse data table. This application also includes a search tool function that can locate programs containing a specified string of SAS code. While the methods presented in this paper apply to intermediate SAS programmers, they can also be modified for use by more advanced programmers. INTRODUCTION Most SAS programmers find it useful to adapt previously written code to new projects. Normally, efficient maintenance of a SAS program file directory depends on internal program code documentation, explaining the intricacies of specific code, and external file documentation, explaining the overall purpose of the program and summarizing any innovative code. The prototype SAS Program File Explorer application illustrated in this article was developed in SAS version 8 on the Windows NT platform. It modifies Mr. Gary Cunningham s technique for creating an index of SAS programs to enable display of program file summary information in table format, searching directories for specific SAS program code, and submitting and viewing selected SAS programs. The application is presented in three parts. First, the base SAS code for creating a SAS program file indexing program is presented. Second, the SAS/AF techniques for developing the frame, frame objects, and SCL are explored. Third, additional base SAS code is given which can be used to create a search mechanism for the application. In reading this paper, please consider the following. Directory information read into SAS using the pipe varies across operating system and operating system version. Section 2 of programs.sas and section 1 of search.sas might need to be changed to reflect this. In addition, this program was creating using SAS files with short file extensions. As a result, this application will include SAS version 8.0 data sets and catalogs with long file extensions in the SAS program file listing unless the application is modified. Finally, some familiarity with SAS/AF is assumed. CREATING A BASE SAS INDEXING PROGRAM Below, the file programs.sas, a modification of Mr. Cunningham s program, is reviewed. This file, which obtains information on SAS program files within a specified directory, is divided into 4 sections that are explained separately. SECTION 1 Descriptive headers are the backbone of this application, since this information is captured and displayed on the program directory frame. In order to fully take advantage of the application, all SAS program files should have a header. Otherwise, only file name and file modification date will be displayed. Additionally, the header structure should remain uniform across programs. Note that the programming techniques below can be used to add additional header categories /******************************************** * Program Name: programs.sas * Description: SAS program dir, mod. of 66-25 * Date: 06/13/2000 * Modified: 08/02/2000; 1/9/2001 * Author: Rob Nelson * Comments: All pgm hdrs should use format! ********************************************/ SECTION 2 In this section, the macro %progindx is created. This macro is ed from the SAS program file explorer application each time a new directory is opened. The directory is fed to the macro using the parameter &dir. An unnamed pipe is used to create a SAS data set, named pgmdat, containing file name and file creation date for all files in the directory with the extension.sas. %macro progindx(dir=); options nodate nocenter number; /******************************************** Index function - which searches source for string - could be used to make sure that path passed in is correct: if index(dir,'(default)') then endsas; Use a pipe to create list of all SAS programs ********************************************/ /* Clear old data sets */ proc datasets; delete pgmdat allpgm pgmdes sasprogs; /* Unnamed pipe obtains file info. &dir given in SCL */ filename fileinfo pipe "dir &dir.\*.sas"; data pgmdat (KEEP=PGM DATE); infile fileinfo length=l; input @; input @1 line $varying200. l; pgm=substr(line,40,50); pgm = upcase(pgm); date=substr(line,1,8); if substr(date,3,1)='/' and pgm NE ' '; filename fileinfo clear; SECTION 3 Next, the first 10 lines of each SAS program file identified in the previous step are parsed for a description. This information is stored in the data set pgmdes. If the header convention shown in step 1 is not used, description data will be not included. The dataset pgmdes is then merged with the data set from section 2, pgmdat to create sasprogs. /* Determine num of SAS pgms*/ set pgmdat end=eof; if eof then symput ('total',left(_n_)); /** Retrieve program SAS pgm file descrip **/ %if &total NE 0 %then %do i=1 %to &total; %let pgm=;

set pgmdat; if _n_=&i; symput('pgm',trim(pgm)); symput('dat',trim(date)); filename saspgm "&dir.\&pgm"; data pgmdes (keep=program descript date); length program $ 200; infile saspgm missover lrecl=200 pad obs=10 end=eof; input @1 line $200.; retain gotdesc 0; drop colon i; program="&pgm"; date="&dat"; if index(upcase(line),'description:') > 0 THEN DO; colon=index(line,':'); do i=1 to colon+1; substr(line,i,1)=' '; gotdesc=1; descript=left(line); output; if eof and gotdesc=0 then do; descript=' '; output; set sasprogs pgmdes; if _n_=1 and program=' ' then delete; filename saspgm clear; % /* If no SAS pgm files, create blank ds */ %else %do; data sasprogs(keep=program descript date); attrib program length=$25 descript length=$100; % SECTION 4 In the final step, macro variables are created which will be used to supply column width to the AF application. The data set is also sorted for display, and the macro definition ended. /* Create str len macro vars to */ /* dynamiy control col width in SCL */ /* (labeled sections update & btnsearch) */ set sasprogs end=last; attrib pgmlenc deslenc length=$8; retain pgmlen 15 deslen 15; label program='program' descript='description' date='date'; if length(trim(pgm)) > pgmlen then pgmlen=length(trim(pgm)); if length(trim(descript)) > deslen then deslen=length(trim(descript)); if last=1 then do; pgmlenc=pgmlen; deslenc=deslen; symput('pgmlen',pgmlenc); symput('deslen',deslenc); proc sort data=sasprogs; by program; %mend progindx; CREATING THE SAS/AF INTERFACE The application s frame layout is illustrated below in Figure 1. The frame is named programs. Table 1 lists object name and type. Object text and labels are shown in the figure. Note that the text entry object is used for all text, including labels. This allows more flexibility, particularly with background color. However, the following object attributes must be ste to use text entry objects in place of text labels: borderstyle= None, editable= No. Also, the commandonclick property of btnexit should be set to End. Finally, the use object name as id in scl box should be checked in the property box of the object tblprogs. Figure 1 - Frame Layout Table 1 Object List No. Name Object type 1 lbltitle Text entry control 2 tblprogs Data table 3 ntndir Push button 4 lbldirlabel Text entry control 5 lbldirdisplay Text entry control 6 containerbox1 Container box 7 entsearch Text entry control 8 btnsearch Push button control 9 lblsearch Text entry control 10 btnopen Push button control 11 btnexit Push button control 12 lbltotobs Text entry control 13 lblnumfiles Text entry control 14 lblnumfound Text entry control 15 lblfound Text entry control PROGRAMS.SCL After creating the frame and all objects, add the following frame SCL. This code allows the user to select a program file directory, search for a string of code within the SAS program files in that directory. Several features of this code deserve mention. Submit blocks are used to run the Base SAS programs programs.sas and search.sas. These programs should be tested before starting frame development. The filedialog function is used to a directory dialog box. This is used both at application start-up, and when the user changes directory. Column width in the data table is controlled using the _setcolumnattributes method. init: _frame_=_frame_; length dat1 8 direct progg program $50; declare object expid datable, num pgmvar desvar codvar X Y, char string1 pgmbox findcnt; /* Position form */ _frame_=_frame_; dcl num col row scol srow; col=round((winfo('maxcol')),1); row=round((winfo('maxrow')),1); 2

_frame_._setwindowsize(1,1,row,col); _frame_._get_widget_('tblprogs',datable); symput('pgmlen',' '); symput('deslen',' '); symput('dirtex',' '); * select directory dialog box; rc=filedialog('aggregate',director,'','','*.s as','','','','','','','','','','','choose SAS Program File Directory', '','','','','','','','','',''); if rc NE 0 then goto errdir; else do; lbldirdisplay.text=director; goto update; update: direct=trim(lbldirdisplay.text); symput('direct1',direct); %include 't:\serodata\sasapps\dev\sugi\programs.sas'; %progindx(dir=&direct1); DATA _null_; CALL SYMPUT('totobs',numobs); STOP; SET work.sasprogs NOBS=numobs; RUN; rc=open('work.sasprogs','u'); dat1=dsid('work.sasprogs','u'); datable._setdataset('work.sasprogs'); datable._displaycolumnlabel('program','date', 'descript'); datable._setdisplayedcolumns('program','descr ipt','date'); pgmvar=((symget('pgmlen') + 1) * 5); *BECAUSE UPCASE; X=(SYMGET('DESLEN')); If X < 4 then X=4; Y=(SYMGET('CODLEN')); If Y < 4 then Y=4; desvar=(x - 1) * 4.5; codvar=(y - 1) * 4.5; datable._setcolumnattribute('program','column _WIDTH',pgmvar); datable._setcolumnattribute('descript','colum N_WIDTH',desvar); * HOLD COLUMN 1; heldcol=makelist(); heldcol=insertn(heldcol,1,1); tblprogs._set_held_columns_(heldcol,heldcol); heldcol=dellist(heldcol); lbltotobs.text=trim(left(symget('totobs'))); lblfound.visible='no'; lblnumfound.visible='no'; btnopen: datable._getcolumntext('program',progg); execcmd('wedit "' trim(direct) '\' trim(progg) '" Use'); btndir: *start in previously selected directory; prevdir=director "\*.sas "; rc=filedialog('aggregate',director,'','',prev dir, '','','','','','','','','','','Choose SAS Program File Directory', '','','','','','','','','',''); lbldirdisplay.text=director; datable._setdataset(' '); rc=close(dat1); goto update; btnsearch: if lbltotobs.text='0' then goto errsearch1; string1=entsearch.text; if string1='' then goto errsearch2; datable._setdataset(' '); rc=close(dat1); symput('search',string1); symput('findcnt',' '); %include 't:\serodata\sasapps\dev\sugi\search.sas'; %strfind(&search,dir=&direct1); entsearch.text=''; rc=open('work.sasprogs','u'); dat1=dsid('work.sasprogs','u'); datable._setdataset('work.sasprogs'); datable._displaycolumnlabel('program','date', 'descript'); datable._setdisplayedcolumns('program','descr ipt','date','finds'); pgmvar=((symget('pgmlen') + 1) * 5); *BECAUSE UPCASE; X=(SYMGET('DESLEN')); If X < 4 then X=4; Y=(SYMGET('CODLEN')); If Y < 4 then Y=4; desvar=(x - 1) * 4.5; codvar=(y - 1) * 4.5; datable._setcolumnattribute('program','column _WIDTH',pgmvar); datable._setcolumnattribute('descript','colum N_WIDTH',desvar); datable._hidecolumn('finds'); * HOLD COLUMN 1; heldcol1=makelist(); heldcol1=insertn(heldcol1,1,1); datable._set_held_columns_(heldcol1,heldcol1) ; heldcol1=dellist(heldcol1); * DISPLAY NUMBER FOUND; lblfound.visible='yes'; lblnumfound.text=trim(left(symget('findcnt')) ); lblnumfound.visible='yes'; errsearch1: warnlist=insertc(warnlist,'no SAS programs in dir'); errsearch2: warnlist=insertc(warnlist,'please enter string'); 3

errdir: *********************************** use dsid function to see if data set work.programs exists (see above); ***********************************; data sasprogs(keep=program descript date); attrib program length=$25 descript length=$100; warnlist=insertc(warnlist,'you must select a directory'); Once the frame SCL has been added, include the following SCL for the data table object TBLPROGS. Remember to compile the data table SCL before compiling the frame SCL. This is done by selecting the data table object in the frame build environment, left mouse clicking, and selecting Table and Compile SCL from the resulting menus. init: dcl object datable, char finds; _viewer_=_viewer_; if finds='y' then do; send(_viewer_,'_setviewerattribute','program','bcolor','yellow'); send(_viewer_,'_setviewerattribute','descript ','bcolor','yellow'); send(_viewer_,'_setviewerattribute','date','b color','yellow'); CREATING A BASE SAS SEARCH PROGRAM The Base SAS program search.sas, is a modification of programs.sas. It searches SAS program files in the chosen directory for a specified string of code. The search feature of the application does not have to be included for the application to work. To exclude this feature, remove the objects btnsearch, entsearch, lblsearch, lblnumfound, lblfound and the SCL code blocks btnsearch, errsearch1, and errsearch2. SECTION 1 This section begins the macro %strfind. A data set nalled flmns is created, containing file name for each of the files in the directory. /************************************** * Program Name: search.sas * Description: Searches SAS program directory program for string, mod. of SAS SUGI 25-66 * Author: Rob Nelson ***************************************/ %macro strfind(str,dir=); options nodate nocenter number pageno=1 ps=50 ls=100; proc datasets; delete flnms str1 pgmstr search; filename fls pipe "dir/b &dir.\*.sas"; data flnms; infile fls length=l; length filename $200; input @; input @1 filename $varying200. l; filename = upcase(filename); filename fls clear; *determine num of SAS pgms & get pgm descript for each; set flnms end=eof; if eof then symput ('total',left(_n_)); data search; SECTION 2 In this section, the first 10 lines of each SAS program file in the directory are searched for header information. %if &total NE 0 %then %do i=1 %to &total; %let pgm=; set flnms; if _n_=&i; symput('pgm',trim(filename)); filename pgm "&dir.\&pgm"; data pgmstr (keep=program finds findstr string); infile pgm missover lrecl=200 pad end=eof; attrib find length=$3. program format=$varying200.; input @1 line $200.; retain findstr 0; program="&pgm"; string=upcase("&str"); if index(upcase(line),string) > 0 THEN findstr=1; if findstr=1 then finds='y'; if eof then output; data search; set search pgmstr; if program='' then delete; filename pgm clear; % SECTION 3 Finally, results from the search are combined with the existing data set containing information on SAS program files. PROC freq is used to provide the number of files encountered to the SAS/AF application. data work.search; set work.search; attrib indxvar length=$200; indxvar=program; data work.sasprogs(keep=indxvar program descript code date); set work.sasprogs; attrib indxvar length=$200; indxvar=program; proc sort data=work.search; 4

proc sort data=work.sasprogs; data sasprogs(drop=indxvar); merge search sasprogs; proc freq data=work.sasprogs; tables finds / NOPRINT out=findcoun; data work.findcoun; set work.findcoun; symput('findcnt','0'); if finds='y'; symput('findcnt',count); proc sort data=sasprogs; by program; %mend strfind; CONCLUSION This application illustrates the usefulness of combining the interactive features of SAS/AF with the flexibility of Base SAS. The authors hope that use of this application will encourage documentation of Base SAS programs and consistent selection of storage location. Additional features for this application might include a tree display of the directory structure, allowing users to select and submit SAS programs without opening, and predesignation of user start directory. REFERENCES Cunningham, Gary An Automated Method to Create a Descriptive Index for a Directory of SAS Programs, SAS Institute Proceedings of the Twenty-Fifth Annual SAS Users Group International Conference, Cary, NC: SAS institute Inc. SAS Institute Inc. (1999), SAS OnlineDoc Version 8., SAS Institute Inc., Cary, NC: SAS Institute Inc. CONTACT INFORMATION Contact the author at: Rob Nelson Centers for Disease Control & Prevention Mailstop E-48 1600 Clifton Road Atlanta, GA 30333 E-mail: RXN1@CDC.GOV 5