Top Banner
r f. ! , .. SAS-based verification of double entry data in a FOCUS® database. Introduction The verification of double entry data was looked at with a problem solving approach. This resulted in a SAS/AF®l application called VERIFY. The VERIFY application is a general purpose verification program that extracts data from double entry data files in Focus@f. It compares the two sets of data and produces printed reports of the verification steps. SETUP Andre Gravel Marion Merrell Dow Table I MAS file - Structure of the database FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = PAT_SEG, SEGTYPE = Sl, FIELDNAME = PATIENT, ALIAS = PAT FIELONAME =FML , ALIAS = FML FIELONAME =AGE , ALIAS = AGE FIELDNAME =SEX , ALIAS = SEX ACCEPT = 'M' 'F' '.' ,$ , FORMAT = A12,$ , FORMAT = A3,$ FORMAT = n,$ , FORMAT = A1, FIELDNAME =INV_NUM , ALIAS =CENTER , FORMAT = I2,$ SEGNAME = ECG_SEG, PARENT = PAT_SEG,SEGTYPE = Sl, FIELONAME = ENUM , ALIAS = ENUM ,FORMAT =I2 ,$ FIELDNAME = LISIBLE ,ALIAS = LISIB ,FORMAT =I2 , ACCEPT = 1 2 3 4 -1 ,$ FIELDNAME = ECG_OATE , ALIAS = EOATE FIELDNAME = ECG_TIME , ALIAS = ETIME FIELDNAME = HR , ALIAS = AHR FIELDNAME = PR , ALIAS = APR FIELDNAME = QRS , ALIAS = AQRS FIELONAME = QT , ALIAS = AQT FIELDNAME = QTC , ALIAS = AQTC FIELDNAME = NORMAL ,ALIAS = NORM ACCEPT = 'A' 'N' '.' ,$ , FORMAT =I6YMD,$ , FORMAT =P5.2,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =Al , FIELDNAME = ECG1_COOE, ALIAS = ECOOEl , FORMAT =PS.2,$ FIELDNAME = ECG_COMl , ALIAS = ECOMl ,FORMAT =A60,$ FIELONAME = ECG_COM2 , ALIAS = ECOM2 ,FORMAT =A60, $ FIELDNAME = ECG_COMJ , ALIAS = ECOMJ FORMAT =A60,$ '=- euiaegmentl FOCUS® and SAS® software runs on a VAXTM 3100 model 80 . The host operating system is VMSTM 5.5 - 2H4. VT300™ emulation is used on PC workstations to connect to the hose. _1 "".2 _3 vor5 s"ubsegmetlt t I_I _I vo.2 -t _3 ._gmcnt2 vo.1 voof "".3 vo.4 Figure 1 - Segmentation 1 SASlAF®, SAS® software are registered trademarks of SAS InstiMe, Cary, NC, USA. 2 FOCUS® is a registered trademark of Information Builders Inc, 3 VT300™. VMSTM are trademarks of Digital Equipment Corporation. 937
22

FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

Apr 21, 2018

Download

Documents

vantuyen
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

r f.

! , ...

SAS-based verification of double entry data in a FOCUS® database.

Introduction

The verification of double entry data was looked at with a problem solving approach. This resulted in a SAS/AF®l application called VERIFY. The VERIFY application is a general purpose verification program that extracts data from double entry data files in Focus@f. It compares the two sets of data and produces printed reports of the verification steps.

SETUP

Andre Gravel Marion Merrell Dow

Table I MAS file - Structure of the database

FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = PAT_SEG, SEGTYPE = Sl, FIELDNAME = PATIENT, ALIAS = PAT FIELONAME =FML , ALIAS = FML FIELONAME =AGE , ALIAS = AGE FIELDNAME =SEX , ALIAS = SEX

ACCEPT = 'M' 'F' '.' ,$

, FORMAT = A12,$ , FORMAT = A3,$

FORMAT = n,$ , FORMAT = A1,

FIELDNAME =INV_NUM , ALIAS =CENTER , FORMAT = I2,$

SEGNAME = ECG_SEG, PARENT = PAT_SEG,SEGTYPE = Sl, FIELONAME = ENUM , ALIAS = ENUM ,FORMAT =I2 ,$ FIELDNAME = LISIBLE ,ALIAS = LISIB ,FORMAT =I2 ,

ACCEPT = 1 2 3 4 -1 ,$ FIELDNAME = ECG_OATE , ALIAS = EOATE FIELDNAME = ECG_TIME , ALIAS = ETIME FIELDNAME = HR , ALIAS = AHR FIELDNAME = PR , ALIAS = APR FIELDNAME = QRS , ALIAS = AQRS FIELONAME = QT , ALIAS = AQT FIELDNAME = QTC , ALIAS = AQTC FIELDNAME = NORMAL ,ALIAS = NORM

ACCEPT = 'A' 'N' '.' ,$

, FORMAT =I6YMD,$ , FORMAT =P5.2,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =I3 ,$ , FORMAT =Al ,

FIELDNAME = ECG1_COOE, ALIAS = ECOOEl , FORMAT =PS.2,$ FIELDNAME = ECG_COMl , ALIAS = ECOMl ,FORMAT =A60,$ FIELONAME = ECG_COM2 , ALIAS = ECOM2 ,FORMAT =A60, $ FIELDNAME = ECG_COMJ , ALIAS = ECOMJ FORMAT =A60,$

'=-euiaegmentl

FOCUS® and SAS® software runs on a VAXTM 3100 model 80 . The host operating system is VMSTM 5.5 - 2H4. VT300™ emulation is used on PC workstations to connect to the hose.

_1 "".2 _3 vo.~

vor5

s"ubsegmetlt t I_I _I vo.2 -t _3

._gmcnt2

vo.1 voof "".3 vo.4

Figure 1 - Segmentation

1 SASlAF®, SAS® software are registered trademarks of SAS InstiMe, Cary, NC, USA.

2 FOCUS® is a registered trademark of Information Builders Inc,

3 VAX"~, VT300™. VMSTM are trademarks of Digital Equipment Corporation.

937

Page 2: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

'P"f --~~.,,~, ~~~~~~="~~~~ ....

I

,i 'I ~ '.

.'.,

"

DATABASE

The process of designing databases is divided into four steps. Together these steps will bring the database to a clean and final set of data.

The design of the database is assigned to a database analyst. The analyst is responsible for the process from the design of the databaSe to the production of the final set of data. The first step is design, which is closely linked to the data collection form (CRF) used by the clinical research department. This form is different for each study. The content of each form is linked to the data which is collected for a specific study.

Table II - FEX file

VMS 'SET DEFAULT 'VMS directory structure' SET KORE=OFF DEFINE FILE ECGREAD

PATIENT/A20 = PATIENT; ENUM/I2 = ENUM; AGE/I2 = AGE; ECOMl/A60 = ECOMl; EC0M2/A60 = ECOM2; EC0M3/A60 = ECOM3;

END TABLE FILE ECGREAD

PRINT AGE ECOMl ECOM2 ECOM3 BY PATIENT BY ENUM ON TABLE SAVE AS ECGl

END FIN

The analyst starts by defining all the variables that will be entered in the database. The analyst then start programming the structure of the database into a MAS file (see Table 1). Data is divided into segments. For example, demographic data values are usually stored in the first level of segrt;lentation of the database (e.g. the MAIN segment). The data is entered only once and is available from everywhere. Subsegments are then created for specific data in the CRF. If a study is conducted on many weeks, the analyst wil probably define a subsegment called WEEK. Subsubsegments may then be created under the MAIN segment or under the WEEK segment depending of the level for which it applies (e.g. ECGs, Vital signs, Emetic episodes, ... ). Figure 1 shows the segmentation of the data structure.

Table m - Screen design

&:~S~GE, _____________________________________ &:~AroS __

&:PROCESS_ &:GOBA~ &:CLEAR __ &:QUIT_

Drug level: &:P &:DR File name: &:FILENAME Main protocol file: &:FICHIERl__ .. Double entry: &:FICHIER2 __ Data type: &:TYPE Same dir?: &:S~ Keys: &:IDVAR'--::-:-:-:----:=::-=:= ____________________ ___ Extraction condition: &:EXT_COND, _______________________ _ Working ,directory : &:WORKDIR.~ _______ --".__--Paper disp: &:PAPER- Clean after? &:NO

Segment names:

Level 1 : Level 2 : Level 3 : Level 4 : Level S : Level 6 :

Variables:

&:SEGMTl_ &:FSl &:LSl &:SEGMT2_ &:FS2 &:LS2 &:SEGMT3_ &:FS3 &:LS3 &:SEGMT4_ &:FS4 &:LS4 &:SEGMTS_ &:FSS &:LSS &:SEGMT6_ &:FS6 &:LS6

&:SEGl __ &:Fl_ &:Ll_ &:SEG2_ &:SEG3 __ &:F3_ &:L3_ &:SEG4_ &:SEGS __ &:FS_ &:LS_ &:SEG6_ &:SEG7 __ &:F7_ &:L7_ &:SEG8_ &:SEG9 __ &:F9_ &:L9_ &:SEGlO_ &:SEGll_ &:Fll &:Lll &:SEGl2_ &:SEGl3_ &:F13 &:Ll3 &:SEGl4_ &:SEGlS_ &:FlS &:L1S &:SEG16_

938

&:F2_ &:L2_ &:F4_ &:L4_ &:F6_ &:L6_ &:F8_ &:L8_ &:FlO &:LlO &:Fl2 &:Ll2 &:F14 &:Ll4 &:F16 &:Ll6

~ ~-- -- - .. -_. --.~ - - --~~ :~' .. ':'- -.~ .. ~'.;~.~,..~-..::-~.-.-

j

!, ' ...

Page 3: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

Once the programming of the database structure is done, the analyst writes input screens for data entry. Double data entry is then performed by data entry personnel. Once the database is completely entered, the analyst writes a verification program that is specific to is database structure. Verification is then applied to the database. After validation (data verification + data correction), the database is ready for analysis. The four steps of this work can be summarized as: database design, screen design, data entry Table IV - FfM file and validation.

PROBLEM

Looking at the situation with many different studies running at the same time and having many different databases, a question was raised: Is it possible to write an application that would allow people to compare FOCUS® data without having to write a verification program each time a new database is designed?

84063 84063 84144 84144 84171 84171 84191 84191 84192 84192 84193 84193 84194 84194 84195 84195

Table V - SAS program generating working file

FILENAME ECG1 'ECG1.FTM';

DATA ECG1; INFILE ECG1 MISSOVER PAD ; LENGTH PATIENT $ 20 ENUM 8

AGE 8 ECOM1 $ 60 ECOM2 $ 60 ECOMJ $ 60

RETAIN ; RETAIN PROTOCOL 'Protocol number'

, FORMAT PATIENT

ENUM AGE ECOM1 ECOM2 ECOM3 ,

$CHAR20. 2. 2. $CHAR60. $CHAR60. $CHAR60.

INPUT PATIENT $ 1-20 ENUM 21-22 AGE 23-24 ECOM1 $ 25-84 ECOM2 $ 85-144 ECOMJ $ 145-204

RUN;

SOLUTION

145 245 124 224 163 263 125MIXTURE OF 2 DIFFERENT ECG'S 225PRECORDIAL LEADS MISSING 131CODE 42 - INCOMPLETE 231 132 232 141 241 141 241

The first part of the project was the design of a screen. This screen contains (table 2) entry fields describing the information about the FOCUS® database (e.g. directories, file names, variable names, variable types and size). The second part of the project is the program. This part is divided into four parts: data extraction; SAS® working files, verification of data, printouts.

939

Page 4: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

The data extraction section generates FEX files (executable command files) containing the extraction codes of the variables the user wants to analyse in the database. The table 3 show an example of a FEX file. Two FEX files are generated. Each file is

Table VI - SAS output

OBS PATIENT

1 84063 Z 84063 3 84144 4 84144 5 84171 6 84171 7 84191 8 84191 , 84192

10 84192 11 84193 12 84193

CCIIIIP&1"i."" Results for ObservatiODll

PATIENT-84U1 EIIUII-Z: Variable Base Value CCIIIIP&1"e

ECOII1 PIUIICORDIAL L PIIBCORDIAL L

PATI_841'4 E11U11-1: Variable Base Value Compare Diff. , Dift

AGE 31 41 10.000000 32.258065

PATIENT-84618 EIIUII=l: Variable Base Value Compare

BCOII3 AlII) LA'l'ERAL

PATIENT-84618 EIIUII-Z: Variable Base Value campare

BCOII3 COII'l'EIt'l'

PATIENT:84667 EIIUII=l: Variable Base Value Compare

1!IC0II3 COIIOHARY SIB

FILl!: 1ICGl, bt I!tI'1'1lY.

VARIABI.I!:S lIrl'II LENGTH LONGER Tiwr 10 CIIAMC'1'I!:RS

EIIUII

1 :2 1 :2 1 :2 1 Z 1 Z 1 2

IICOIIl

IIIlt'1'IIItI!: 01' :2 DIPI'I!:REIIT I!ICG'S PRECORDIAL LEAD IIISSING CODS 42 - IHCOIIPLETB

generated for each data entry (1st and 2nd). These FEX files are submitted interactively by the application using the following command:

X 'FOCUS -EX name·'

The -names is replaced by the actual name of the FEX generated file. The SAS® option NOXWAIT allows automatic return to the SAS® application after each FEX file is submitted. Each submission will generate a FTM file containing the data in ASCII format (table 4).

The next step is to read the ASCII data into working SAse files. This step uses the data description (screen level) to define the LENGTH, FORMAT and INPUT statements in the SAS® programs. Two programs are generated to read in the data that was extracted at the previous step. (see table 5 for an example of the generated SAS code). Once the programs are generated into ASCII files, they are interactively submitted to. the SAS® system.

Once the two working files are available the verification program is generated into an ASCII file (table 6) using the deSCription from the screen entry. Once this program is generated, it is submitted to the SAS® system.

The generated verification program uses the COMPARE procedure. Each COMPARE

940

Page 5: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

procedure (up to three compare procedure are generated by the program) generates an output to the screen (table 7) that can be printed to a printer. If character strings longer than 10 character are tested by the verification program then a print procedure is generated by the program to print these strings (table 7). This part of the program is included since the COMPARE procedure only prints the first 12 character of each string.

Table vn - Verification SAS program

PROC SORT DATA=ECGl; BY PATIENT ENUM; RUN;

DATA ECGl; RETAIN CNTI CNT2; SET ECGl; IF LAG(PATIEN'I) "= PATIENT THEN

CNTl=l; ELSE CNTl+l; IF LAG(pATIEN'I) "= PATIENT THEN

CNT2=I; ELSE CNT2+1; RUN;

PROC SORT DATA=ECG2; BY PATIENT ENUM; RUN;

DATA ECG2; RETAIN CNTI CNT2; SET ECG2; IF LAG(PATIENT) "= PATIENT THEN

CNTl=l; ELSE CNT1+1; IF LAG(PATIEN'I) "= PATIENT THEN

CNT2=I; ELSE CNT2+1; RUN;

OPTIONS PAGENO = 1;

PROC COMPARE BASE=ECGl COMPARE=ECG2 ListEqualVar Transpose MaxPrint = 1200;

ID PATIENT ENUM; TITI..El "&HEAD 1"; TITI..E2 "&HEAD2"; TITI..E4 'UNEQUAL VALUES BY PATIENT

ENUM'; FOOTNOTE "&FooTl"; RUN;

941

Page 6: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

CONCLUSION

This application has saved many hours of coding and has reduced the number of encoding errors. Less error occurs because no encoding is needed by the database analyst on the verification process. This application reduces to a minimum the knowledge needed to do the verification step. All the analysts uses the same interface and get the same results from the analysis. The program is versatile and can be used on all kink of FOCUS® databases.

Still, there is a need to add filing facility to the application. The correction of character strings is still cumbersome and needs to be revisited.

The problem solving approach has given us the chance to tackle the problem of data verification. The VERIFY application is now used to verify all databases at our site. The SAS® software has helped us build a good solution.

942

1-· . • :- ... ,

Page 7: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

~ ~. i:

l'; ;: 1. '~j

~ ! t~ ~2~ £1 ~! ~ }J 1,

I 'I ), ~,

t P: ~i l' ti r; e·

i to p " ~.

~ ,

I 'i

I \ t,

\.

~

I ~ ;-

SOURCE CODE

/****************************************************************************/ /* VERIFY - Focus extraction window for main entry and second entry */ /* COPYRIGHT 1993-94 Marion Merrell Dow, Strasbourg, FRANCE */ /*-==========================~=============================================-*/ /* Author: Andre Gravel, eng. * / /* oate created: September 1, 1993 */ /*-========================================================================-*/ /* Content: This program is used to extract data entry from a focus */ /* file with is double entry and then compare these values * / /* */ /* Internal ref: INIT, MAIN, TERM, PROCESS, CLEARUP */ /* */ /* Variables: (Uppercase variables are those used in the SAS */ /* file definition) * / /* file - Name of the FOCUS Study file * / /* drug - Drug number * / /* prefix - Used prefix in the protocol naming */ /* rc - return code from function calls * / /* source Source name given to working files */ /* fid - File ID pointer * / /* */ /* OR - Drug level */ /* * / /* FICHIERl - Study Identification number */ /* */ /* FICHIER2 - double entry Identification number * / /* */ /* SEGMENTl - Main variable for 1st segment to 6th segment * / /* SEG~6 */ /* * / /* SEGOOl-4S Variables to extract in all segments */ /* */ /* FOl-4S - Format of variables to extract */ /* * / /* LOl-4S - Length of each variables to extract */ /* */ /* vc Variable counter */ 1* j - Counter * / /* pass Flag */ /* choice - Selection variable */ /* * / /* */ ,,********-******************************************************************/

INIT: array Vars{*} $ DRUG FILENAME Vl FICHIERl FICHIER2 TYPE; array VarName {*} $ S (' DRUG' , , FILENAME' , , Vl' , , FICHIERl' , , FICHIER2' , 'TYPE' ) ;

array sag{*} $ SEGMT1-SEGMT6 SEG1-SEG4S;

array feW} array leW}

$ FS1-FS6 Fl-F4S; LS1-LS6 Ll-L4S;

array sagName{*} $ S

array FName{*} $ S

array LName{*} $ S

('SEGMT1','SEGMT2','SEGMT3','SEGMT4', 'SEGMTS','SEGMT6', 'SEG1','SEG2','SEG3','SEG4','SEGS', , SEG6' , , SEG7' , , SEGS' , , SEG9' , " SEG10' , 'SEGll', 'SEG12','SEGl3','SEGl4','SEG1S', 'SEG16','SEG17','SEGlS','SEGl9','SEG20', 'SEG2l','SEG22','SEG23','SEG24','SEG2S', 'SEG26','SEG27','SEG2S','SEG29','SEG30', 'SEG3l','SEG32','SEG33','SEG34','SEG3S', 'SEG36', 'SEG37', 'SEG3S','SEG39','SEG40', 'SEG4l','SEG42','SEG43','SEG44','SEG4S', 'SEG46','SEG47','SEG4S' ) ;

('FSl', 'FS2', 'FS3', 'FS4', 'FSS', 'FS6', 'Fl', 'F2', 'F3', 'F4', 'FS', 'F6', 'F7', 'FS', 'F9', 'FlO', 'Fll','F12','Fl3','Fl4','F1S', 'Fl6','Fl7','FlS','Fl9','F20', 'F2l','F22','F23','F24','F2S', 'F26', 'F27', 'F2S', 'F29', 'F30', 'F3l','F32','F33','F34','F3S', 'F36','F37','F3S','F39','F40', 'F41','F42','F43','F44','F4S', 'F46','F47','F4S' );

('LSl','LS2','LS3','LS4','LSS','LS6', 'Ll', 'L2', 'L3', 'L4', 'LS', 'L6', 'L7', 'LS', 'L9', 'LlO', 'Lll','Ll2','L13','L14','L1S', 'L16','L17','L1S','L19','L20',

943

l ~

Page 8: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

'L21','L22','L23','L24','L2S', 'L26','L27','L2S','L29','L30', 'L31','L32','L33','L34','L3S', 'L36' , 'L37' , 'L3S' , 'L39' , 'L40' , 'L41' , 'L42' , 'L43' , 'L44' , 'L4S' , 'L46', 'L47', 'L4S' . ) ;

VarStart = 7; 1* After segment definition *1 blank = I{VarStart}; message = "; call setcr('htab','return','nomodify'); call display ( 'message' ) ; status = 'Reading';

return;

MAIN: 1**** Validate data entry ****1 erroroff _all_; message = "; 1*** Segments and associated variables ***1 do i = 1 to dim(seg);

if seg{i} A= " then do;

if f{i} = " then do;

rc = field('erroron',fname{i}); rc = field('cursor',fname{i}); Message = 'Type must be entered ' II

'since 'I Iseg{i}1 I' was specifiedt'; status = 'Reading'; refresh; return;

end; else

do;

end;

if l{i} = . or lei} = blank then do; rc = field('erroron',lname{i}); rc = field('cursor',lname{i}); Message = 'Length must be entered for variable '

Ilseg{i} II' !'; status = 'Reading'; refresh; return; end;

if lei} <= 0 or lei} > 200 then do; rc = field('erroron',lname{i}); rc = field('cursor',lname{i});

end;

Message = 'Illegal length for variable ' II seg{i} II' !';

status = 'Reading'; refresh; return; end;

else

end;

do; f{i} l{i} =

end;

, I ;

blank;

select (LEFT(choice»;

when ('QUIT') when ('GOBACK') when (' CLEAR' )

call display('exit.program'); call execcmd(' End');

do; idvar = 'patient'; filename :: "; do i = 2 to dim(seg);

seg{i} = "; f{i} :: "; lei} :: blank;

end; cursor segmtl; cursor filename; status :: 'Reading'; refresh;

end; when (' PROCESS' )

do; status = 'Processing'; refresh; 1*** Test P ***1 if P :: •• then

do;

944

Page 9: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

rc = field("erroron","P"); rc = field("cursor","P"); message = "Prefix of DRUG is needed for DATA extraction."; status = 'Reading'; refresh; return;

end;

/*** Test Main variables ***/ do i = 1 to dim(vars);

if vars{i} = "" then

end;

do; rc = field("erroron",varname{i}); rc = field("cursor",varname{i}); message = varname{i} II " must be specified!"; status = 'Reading'; refresh; return;

end;

/*** Test IDVAR ***/ if IDVAR "" then

do; rc field("erroron","IDVAR"); rc = field("cursor","IDVAR"); message = "At least one key variable must be specified!"; status = 'Reading'; refresh; return;

end;

/*** Verify if keyfields are valid ***/ n = 1; tempname = scan(idvar,n,' '); DO while (tempname "= "");

flag = 0; do i =.1 to dim(seg);

if tempname = seg{i} then flag 1; end; if flag = 0 then

do; rc = field("erroron","IDVAR"); rc = field("cursor","IDVAR"); message = "Listed .keyfie1ds are not all present " I I

"in list below, please modify!"; status = 'Reading'; refresh; return;

end; n = n + 1; tempname = scan (idvar,n, ' ');

end; link PAPIER; link PROCESS; if CLEAN = ' YES' then link CLEARUP; status = 'Reading'; refresh; alarm;

end; otherwise;

do;

end;

status 'Reading' ; refresh;

end;

choice "; return;

TERM: return;

PAPIER: select (paper) ;

when ( , LANDSCAPE' ) do;

linesize = 132; submit continue;

options ls=132 ps=66; endsubmit; call execcmdi ( "PRTFlLE ITAL_PRN; FORMNAHE ITALIEN;");

end; otherwise

do; linesize = 112; submit continue;

options ls=112 ps=100; endsubmit;

945

'~.~ -~- ,- < -" - ' •• '-

,',. ,. -".- ~ '", -~ . ~ - ;;.: - -.:''- ."' ,--

Page 10: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

\

\

do i = 1 to dim(seg); if seg{i} ~= "" then

call method('routines','DEF~',fid,'E', seg{i},F(i} I I left(put(L{i},best.»);

end;

1***** Fermer la definition des longueurs des champs *****1 rc = fput(fid,"END"); rc = fwrite(fid);

1***** puis DEBUTER l'extraction des variables *****1 rc = fput(fid,"TABLE FILE" I I file2); rc = fwrite(fid); vc=O; 1* Variable counter *1 rc = fput(fid," PRINT ");

do i = VarStart to dim(seg); if seg{i} A= "" then call method("routines","V,AREXT",vc,fid,'E',seg(I});

end;

/****** »> OONT FORGET to insert a line feed. ******/ rc = fput(fid," "); rc = fwrite(fid);

/***** BY segments VARIABLES *****1 vc = 0; /* Variable counter */

do i = 1 to (VarStart - 1); if seg(i} A= "" then

do; rc = fput(fid," BY"); call method("routines","VAREXT",vc,fid,'E',seg(i});

end; end;

rc = fput(fid," "); rc fwrite (fid); i* CRLF *1

if ext cond A= " then call method("routines","PutWrite",fid,4,ext_cond);

status = 'Extracting'; rei'resh;

1***** Save file into "file.PBX" where file is GIVEN by user *****1 call method('routines','SAVEFOC',source2,fid); rc = sysrc(); if (rc) then call display('exit');

1***** SUBMIT the FOCUS file *****/ I~********************************I

rc = system('FOCUS EX" , II source2 II '"'); call method('routines.scl','VERZFY',

source2,'FTM',rc,drug,fichier2);

1*** if the focus file is not created then EXIT ***1 if (rc 0) then return;

status 'Processing'; refresh;

1*** 1***

Validate segment names and associated variable names ***1 before creating SAS variable names ***1

do i = 1 to dim(seg); if seg(i} ~= "" then

do; if indexc(seg(i},'01234567S9') = 1 then /* num in-~st pos */

do;

end; end;

seg(i} = '_' II seg{i}; if length(seg{i}) > S then

seg{i} = substr(seg{i},1,S); end;

I**********************************************~*****************/ 1***** CREATION of the SAS program files *****1 /**************************************************~*************/

status = 'Writing'; refresh; .

call display ( , screen' , "Creating Sas code for " II sourcel);

946

Page 11: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

1***** Assign the SAS file (Open it) *****1 call method('routines','CREATTMP',sourcel,fid,drug,fichier1);

1***** Define: Variable LENGTH, MISSING Values, PREDEFINED 1***** Values and INPUT STATEMENTS for EXTRACTION. do j = 1 to 3;

select (j); when (1) pass

rc = when (2) pass

rc = when ( 3) pass

rc otherwise;

end;

= 'Ll; fput (fid,' = 'F' ; fput (fid,' = 'E'i fput (fid, '

1** Length definition pass LENGTH ') ; 1** Formatting values pass FORMAT ' ) ; /** Extracted values pass INPUT ') ;

vc 0; /** Initialize Variable counter **/

do i = 1 to dim(seg); if seg{i} A= •• then

do;

link CHK_VAR1; 1* Verify' chars in var name *1

select(f{i});

.*.**/ ****~/

**1

**1

**1

when('D') call method('routines', 'SASVAR', pass,fid,'E',seg{i},vc,L{i},F{i},.,8);

when ( , I') call method ( 'routines' , 'SASVAR' , pass,fid,'E',seg{i},vc,L{i},F{i},.,8);

when('Y') call method('routines' ,'SASVAR', pass,fid, 'E',seq{i},vc,L{i}, 'I' ,.,8);

otherwise call method('routines' ,'SASVAR', pass,fid,'E',seg{i},vc,L{i},F{i});

end;

end; end;

rc rc

end;

'" fput(fid,·;"); fwrite(fid) ;

1***»> at the end of each statement *1

call method('routines','PutWrite' ,fid,4, ·+RUN;-};

rc = fclose(fid);

status = 'Processing'; refresh;

/**********************w****************************** *1 1***** We are now ready to submit the SAS Dataset *****/ /***.***-* •• *_ •• *****-****.**.**.****.*** •• ********.** *1 call display('screen' ,"Creating WORK." I I source1 I I

• data set."); submit continue ;

'include '&sourcel.SAS'; run;

endsubmit;

/** SAS file #2 **/

status = 'Writing'; refresh;

call display('screen','Creating Sas code for' I I source2);

1***** Assign the SAS file (Open it) *****1 call method('routines','CREATTMP' ,source2,fid,drug,fichier1);

/***** Define: Variable LENGTH, MISSING Values, PREDEFINED 1***** Values and INPUT STATEMENTS for EXTRACTION. doj=lto3;

select (j); when (1) pass

rc = when (2) pass

rc = when (3) pass

rc otherwise;

end;

= 'L' j

fput(fid,' = 'F'; fput(fid, ' = 'E'; fput (fid,'

/** Length definition pass LENGTH') ; /** Formatting values pass FORMAT '); /** Extracted values pass INPUT ');

vc 0; /** Initialize Variable counter **1

do i = 1 to dim(seg); if seg{i} A= "" then

do;

947

"*.***/ *****/

**/

**/

**/

Page 12: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

link CHK_VARl; 1* Change % character in var name if needed *1

select(f{i}) ; when('D' )

when('I')

when('Y')

otherwise

call method ( , routines' , ' SASVAR' , pass,fid,'E',seg{i},vc,L{i},F{i},.,8);

call method{'routines','SASVAR', pass,fid,'E',seg{i},vc,L{i},F{i}, .,8);

call method('routines','SASVAR', pass,fid,:E',seg{i},vc,L{i}, 'I', .,8);

call method{'routines','SASVAR', pass,fid,'E',seg{i},vc,L{i},F{i})1

end;

end; end;

rc = fput(fid,";"); 1***»>; at the end of each statement *1 rc = fwrite(fid);

end I call method('routines' ,'PutWrite' ,fid,4,

·+RUN; .);

rc = fclose(fid); status = 'Processing'; refreshl

/*************************.****************************/ 1***** We are now ready to submit the SAS Dataset *****1 /***************************************************** *1 call display('screen' ,"Creating WORK." I I source21 I " data set."); submit continue ;

%include '&source2.SAS'; run;

endsubmit;

1** SAS Compare file **1 status = 'Writing'; refresh; call display('screen' ,"Creating Sas Compare code"); refresh;

1** COMPUTE KEY to be selected for counter setup **1 i = 1; do while(scan(idvar,i) ~- , ');

i = i+l; end;

if i <= 2 then i=1; else i = i - 2;

1***** Assign the SAS file (Open it) *****1 call method('routines','SasWkTmp', 'compare',fid,drug,fichierl);

call method ( 'routines' , 'PutWrite' , fid, 1, "+PROC SORT DATA=" I I sourcel I I ";",

BY " II IDVAR I I ";", RUN;· ,

" + DATA " I I sourcel I I ";", RETAIN CNT1 CNT2;", SET " II source1 II ";", IF LAG{"IISCAN(IDVAR,i) I I") ~- "1ISCAN(IDVAR,i)ll" THEN CNT1=l;", ELSE CNT1+1;", IF LAG("IISCAN(IDVAR,1) I I") ~= "1ISCAN{IDVAR,1) II" THEN CNT2=1;", ELSE CNT2+1;", RUN;") ;

call method('routines','PutWrite' ,fid,1, "+PROC SORT DATA=" I I source2 I I ";",

BY " II IDVAR I I ";", RUN;· ,

"+DATA" II source2 II "I", RETAIN CNT1 CNT2;", SET " II source2 II "I", IF LAG{" I ISCAN(IDVAR,i) I I") A= "1ISCAN(IDVAR,i)ll" THEN CNT1=1;", ELSE CNT1+11", IF LAG("IISCAN{IDVAR,1) II") A= "1ISCAN(IDVAR,1)11" THEN CNT2=11", ELSE CNT2+1 I", RUN; ") I

call method('routines','PutWrite' ,fid,1, "+1*** GENERATE ALL HEADERS ***1", "+DATA .-NULL_I", "LENGTH HEAD1 HEAD2 HEAD3 FooT1 $ 132;", "+HEAD1 = 'Title .1';", "HEAD1 = TRIM(HEAD1) II REPEAT (' ',"I!put (linesize, 3.) II

" - LENGTH{HEAD1»;", "CALL SYMPUT('HEAD1',HEAD1);");

name = getjpi('username'); call method{'routines','PutWrite',fid,1,

948

Page 13: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

'HEAD2 = 'Title #2';', 'CALL SYMPUT('HEAD2',HEAD2);', '+HEAD3 = 'Observation to observation comparison';', 'HEAD3 = TRIM(HEAD3) I I REPEAT(' ','1 Iput(linesize,3.) I I

• - LENGTH(HEAD3»;', 'CALL SYMPUT('HEAD3' ,HEAD3) ;', '+FOOTl = 'SOURCE: • I I NAME I I ' (&. I I 'SYSDATE,&' II 'SYSTlME) ';', 'FOOTl = TRIM (FOOT1) I REPEAT(' '.'1 Iput(linesize,3.)

• - LENGTH(FOOT1»;', 'CALL SYMPUT('FOOT1',FOOT1);', ·+RUN; -) i

call method('routines', 'PutWrite' ,fid,l, '+OPTIONS PAGENO = 1;", "+PROC COMPARE BASE=' I I source1,

COMPARE=' I I source2, ListEqualVar Transpose' ,

ID TITLEl TITLE2 TITLE4

MaxPrint = 1200;', • I I IDVAR II ';',

'&HEAD1'; , , -&HEAD2· i ' I

'UNEQUAL VALUES BY "I IIDVARI I ";');

if ext cond ~= " then call method('routines','PutWrite',fid,6, 'TITLE6 "1 lext_condl I"i');

call method('routines','PutWrite' ,fid,l, FOOTNOTE "&FOOT1';', RUN;');

call method('routines','PutWrite' ,fid,l, '+OPTIONS PAGENO = 1;', '+PROC COMPARE BASE=' I I source1,

COMPARE=' I I source2, Transpose" ,

ID VAR TITLE1 TITLE2 TITLE4

ListObs' , MaxPrint =

:lli::II: • &HEADl • ; I ,

-&cHEAD2·j',

200; " CNT1;' , CNT1;' ,

'MISSING OBSERVATIONS';');

if ext cond A= " then call method('routines', 'PutWrite' ,fid,6, "TITLE6 '"II ext_condll" ; .) ;

call method('routines' ,'PutWrite' ,fid,l, FOOTNOTE '&FOOT1';',

if

RUN;') ;

SCAN(IDVAR,2,' ') ~= " then do;

call method('routines', 'PutWrite' ,fid,l, '+OPTIONS PAGENO = 1;', '+PROC COMPARE BASE=' I I sourcel,

COMPARE=' I I source2, Transpose' ,

ID VAR TITLE1 TITLE2 TITLE4

ListObs', MaxPrint = 800;', "'ISCAN(IDVAR,l) I I' CNT2;', • IDVARII' CNT2;",

'&HEAD1';', '&HEAD2'; , , 'Unequal keys' ;');

if ext cond ~= " then call method('routines','PutWrite',fid,6, "+TITLE3 '"I lext_condl I";");

call method('routines','PutWrite' ,fid,l, FOOTNOTE '&FOOT1';', RUN;"';

end; rc = fclose(fid); status = 'Comparing'; refresh; /.*****************************************************/ /***** We are now ready to submit the SAS Dataset *****/ I*********·*********~********************************* *1

call display('screen',"Comparing files');

submit continue ;

949

Page 14: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

'include 'COMPARE.SAS'; run;

endsubmit;

1** SAS - PRINT file **1

1** First, verify if we need to do this step **1 1** Need at least one char variable that **1 1** is 11 character in length or more **1

1*** Test Main variables ***1

doit = 0; /* Nothing to do */ do i = VarStart to dim(seg);

if seg{i} A= •• then if f{i} = 'C' and l{i} > 11 then doit = 1; /* DO something 111*/

end;

if doit = 1 then do;

link RECTO; /* SET proper form */

status = 'Writing'; refresh;

call display('screen','Creating Character fields printout code·); refx-esh;

/***** Assign the SAS file (Open it) *****/ call method('routines','SasWkTmp','print',fid,drug,fichierl);

call method('routines','PutWrite',fid,l, '+OPTIONS PAGENO = 1;·, '+OATA • I I sourcel I I .;., • SET • II sourcel , • (KEEP = • II IOVAR);

do i if

end;

VarStart to dim(seg); seg{i} A= •• and f{i} = 'C' and l{i} > 11 call method('routines','PutWrite',fid,l,

• II UPCASE(seg{i}»;

call method('routines','PutWrite',fid,l,

then

) . " ·+TITLE4' 'FI~ • II sourcel I I ., 1st ENTRY.';', 'TITLE6 'VARIABLES WITH LENGTH LONGER THAN 10 CHARACTERS';', -RUN;· , "+PROC PRINT;RUN;");

/*** SECONOFILE ***/

call method('routines','Putwrite',fid,l, '+OPTIONS PAGENO = 1;·, "+OATA • I I source2 I I .;., • SET • II source2 , • (KEEP = • II IOVAR);

do i if

end;

VarStart to dim(seg); seg{i} A= •• and f{i} = 'C' and l{i} > 11 call method('routines','PutWrite',fid,l,

• II UPCASE(seg{i}»;

call method ( 'routines', 'PutWrite', fid,·l,

then

) .. ·+TITLE4' 'FILE· I I source2 II ., 2nd ENTRY.';·, ·TITLE6 'VARIABLES WITH LENGTH LONGER THAN 10 CHARA~;·, -RUN;· , ·+PROC PRINT;RUN;");

rc = fclose(fid);

status = ' Printing' ; refresh;

/******************************************************/ /***** We are now ready to submit the SAS Dataset *****/ /******************************************************/ call display ( , screen' , ·printing files·);

submit continue ; 'include 'PRINT.SAS'; run;

endsubmit;

END;

950

Page 15: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

* call execcmd('End'); /*** Tell the system to close the window ***/ return;

CLEARUP: status 'Cleaning'; refresh;

call method('routines','delfile',sourcel,'FEX'); call method('routines','delfile',sourcel,'FTM'); call method('routines','delfile',sourcel,'SAS'); call method('routines','delfile',source2,'FEX'); call method('routines','delfile',source2,'FTM'); call method('routines','delfile',source2,'SAS'); call method('routines','delfile','COMPARE','SAS'); call method('routines','delfile','PRINT','SAS');

return;

ROUTINES

,,***************************************************************************/ /* Routines SCL */ /* COPYRIGHT 1993-94 Marion Merrell Dow, Strasbourg, FRANCE */ 1*-========================================================================-*' /* Author: Andre Gravel, eng. . * / /* Date created: January 04, 1993 */ I*-====================~===============================================8===-*, /****************************************************************************/

DULEN: I***********************************~***************** ***************/

/* DULEN: Routine expanding the resizing definition for FOCUS */ /* extracted variables. Variables a immediately extracted */ /* at the exact width needed for the new standard. * / I*******~********************************************* ***************/

method fid 8 etat $ variable $ type $; if (etat = 'E') then

do; newform = type; SELECT UPCASE(substr(newform,l,l»;

when("C") substr(newform,l,l) = "A"; when ("Y") newform = "I6YMD"; otherwise;

end; rc = fput (fid. '

'/'

if rc if

, = ' (rc) then _msg_ = fwrite(fid); (rc) then _msg_

1\ upcase(variable) II upcase(newform) I upcase(variable) I sysmsg() ;

sysms~() ; end;

endmethod;

, i ' ) ;

VAREXT: /********************************************************************/ /* VAREXT: Routine expanding the TABLE definition in FOCUS to */ / * activate the extraction of needed variables. * / /,*******************************************************************/

method varcount 8 fid 8 etat $ variable $; if (etat = 'E') then

do; /* write varname into buffer */

rc fput(fid,upcase(variable) II ' '); if (rc) then _msg_ = sysmsg(); varcount = varcount + 1; if (varcount >= 6) then

do;

rc = fwrite(fid); if (rc) then _msg_ varcount = 0;

rc = £put (fid, ' if (rc) then J\sg_

end; end;

endmethod;

sysmsg() ;

') ; sysmsg() ;

/* flush buffer (full) */

/* set indentation */

CreatFoc: '*******************************************************'*******·**~*I /* CREATFOC: This routine Create (delete old files) a FEX file */ /* header for submission to the focus system. */ ,** ••• ***************************************************************1

method fichier $ fid 8 drug $ file $;

951

Page 16: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

Name of the FEX file * I 1* fichier: 1* fid 1* drug

File id for FPUTs and FWRITEs *1 Drug number * I

1* file Drug file's study number *1 fname -, , 1***** Verify first if 'fichier'.FEX exists ... *****1 if (fileexist(fichier I I '.FEX'II then

do; f** *** Delete this FEX file ****.* f rc filename(fname,fichier I I '.FEX'I; rc fdelete(fnamel; rc filename(fname,' 'I;

end; fdata = ' ';

1* ... delete 1* Deassign

/***** Verify first if 'fichier'.FTM exists •.. *****1 if (fileexist(fichier I I '.FTM'II then

do; f***** Delete this FTM file *****1 rc filename(fdata,fichier II '.FTM'I; rc fdelete(fdatal; rc filename(fdata,' 'I;

end;

/* ... delete /* Deassign

*1 *1

*/ */

f***** Assign the file 'fichier'.FEX and prepare it for FOCUS *****/ fname = 'a'; rc = filename(fname,fichier I I '.FEX'I; /* Get fileref */ fid= fopen(fname,'O',lOO,'D'I; /* open file *1

endmethod;

SaveFoc: 1*·**·'·_*-*'**'··"·"·'·"·**'·"··'·"'·*···"·'·'·***************1 1* SaveFoc: Routine ends the trailing focus commands and then close *1 1* the file. *1 1****'·"*·*--**'**'·'·'·""*·'·""*··'·"***_·***" ***************/

method fichier $ 1* file : Name of the study file *1 fid 8; 1* fid : File id number to SAS *f

f***** Save file into file.FEX where file: given by user *****1 1***** Execute by emiting an END statement and QUIT *****1 call method ( 'routines' , 'PutWrite' ,fid,l,

" ON TABLE SAVE AS " II upcase(fichierl, -END- , "FIN"I;

1***** Close the file *****1 rc = fclose(fidl;

endmethod;

CreatTmp: 1******·_***-**·_---'--*_·_---**--**---**'-·_-_·_-*···***************/ 1* CreatTmp: This routine Create (delete old files) a SAS pgm file *1 1* header for submission to the SAS system. NULL file. * I 1*-"--"'·'--'-'--'-"""----'---"---"---"--_··_-*******.'*******/ method fichier $ fid 8 drug $ file $;

1* fichier: Name of the SAS file *1 f* fid File id for FPUTs and FWRITEs * / 1* drug Drug number * I f* file Drug file's study number *1

fname -, 'i

1*·*** Verify first if 'fichier'.SAS exists .•. *****1 if (fileexist(fichier II '.SAS'» then

do; 1***** Delete this SAS file *****1 rc filename (fname, fichier II '.SAS'); rc = fdelete(fnamel;

1* Get fileref *1 1* ... delete *1 1* Deassign *1 rc filename(fname,' ');

end; 1***** Assign the file 'fichier'.SAS and prepare it for SAS *****1 fname =' 'i rc = filename(fname,fichier I I '.SAS'); fid= fopen(fname,'O',lOO,'D'); /***** Set default working directory into call method('routines','PutWrite',fid,l,

1* Get fileref *1 1* open file *1

FOCUS *****j

"FILENAME • II fichier II • ,. II fiehier II ".FTM';·, "+DATA " I I fiehier I I .;., , INFILE' II fiehier II ' MISSOVER PAD ; 'I;

endmethod;

SasWkTmp: 1*"""""""""""""""""""""""'·'·"***************1 1* SasWkTmp: This routine Create (delete old files) a SAS pgm file *1 1* header for submission to the SAS system. NULL file. * / 1***************************************************** ***************/

method fiehier $ fid 8 drug $ file $; 1* fichier: Name of the SAS file *1 1* fid File id for FPUTs and FWRITEs *1 I" drug Drug number * I /* file Drug file's study number *1

fname - I , i f"**"* Verify first if 'fiehier'.SAS exists •.. "****1 if (fileexist(fiehier II '.SAS'») then

952

Page 17: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

do; /***** Delete this SAS file *****/ rc filename(fname,fichier I I '.SAS'); rc = fdelete(fname); rc = filename(fname,' ');

/* Get fileref */ /* •.. delete */ /* Deassign' * /

end; /***** Assign the file 'fichier'.SAS and prepare it for SAS *****/ fname = ' '; rc = filename(fname,fichier II '.SAS'); fid= fopen(fname,'O',100,'D');

/* Get fileref */ /* open file */

endmethod;

length var $ 8;

SasVar: 1**-·""**"·"""""""""""""""""""" ***************/ /* SasVar: This routine creates the SAS Statements to define the */ /* LENGTH, MISSING Values, PREDEFINED Values and */ /* INPUT Statement to read the ASCII file generated by * / /* FOCUS. */ /********************************************************************/

method pass $ /* Pass (L)enght, (M)issing */ /* (P)redefined or (E)xtrated */ /* (F)ormated, (I)mported */

fid 8 /* fid File id number to SAS */ etat $ /* etat State from screen selection */ var $ /* var Variable name */ vc 8 /* vc Counter to end of line */ long 8 /* long Length in new protocol */ type $ /* type Type in new protocol */

optional =forma t 8 /* format Format of the variable */ rlength 8 /* rlength:

/* ;

/***** Select pass number *****/ select (upcase(pass»;

Real length of variable SAS

1*******************************1 /****** LENGTH definition ******/ /*******************************/ when('L')

in */ */

/****** if RLENGTH is not given than take LONG value ******/ if rlength = . then rlength = long; select (upcase(type»;

when('C' ) rc = fput(fid,put(upcase(var),$8.) I I • $ • I I

put(rlength,4.) II •• ); vc = vc + 1;

otherwise /*** define I, Y & D length values ***/ do;

rc fput (fid,put (upcase(var) ,$8.) I I • put(rlength,4.) II •• );

end;

vc end;

vc + 1;

if (vc ge 4) then do;

rc fwrite(fid); vc = 0; rc fput (fid, '

end; /*******************************/ /*** FORMATTED Values ****/ /***************~***************I

when('F')

') ;

• II

/****** if FORMAT is not given than take LONG value ******/ if format = . then format = long; select (upcase(type»;

1***** first, indicate if variable is nUDr~~har *1 1***** year or time */ when('C') 1***** CHARACTER VARIABLES *****/

do; 1** Check len of LONG for output purposes **1

end;

rc = fput(fid,put(upcase(var),$8.) II left(put(format,3.»

when('Y') 1***** CHARACTER VARIABLES *****/

, $CHAR' II , , ) ;

rc = fput(fid,put(upcase(var),$8.) I I ' MKDDYY.');

when('T') 1***** CHARACTER VARIABLES ·****1 rc = fput(fid,put(upcase(var),$8.) I I ' HHMM.');

when('I') /***** INTEGER VARIABLES *****/ do;

/** Check len of LONG for output purposes **/

953

Page 18: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

if (format < 10) then rc = fput(fid,put(upcase(var),$8.) II ' , I I

put ( format, 1.) II '.' ); if (10 <= format < 100) then

rc = fput(fid,put(upcase(var),$8.) II ' , II put(format,2.) II '.');

if (format >= 100) then rc = fput(fid,put(upcase(var),$8.) II ' , I I

put (format,3.) II '.'); end;

otherwise 1***** REAL VARIABLES AND OTHERS *****1 do;

1** Check len of LONG for output purposes **1 if (format < 10) then

rc fput(fid,put(upcase(var) ,$8.) II I I put(format,3.1));

else rc = fput(fid,put(upcase(var),$8.) II ' , II

put(format,4.1)); end;

end;

1***** write the whole thing *****1 rc fwrite(fid); rc = fput(fid,' '); 1* prepare for next line *1 vc = vc + INT(long);

/*******************************/ 1*** FOCUS EXTRACTED Values ****1 /*******************************/

when('E') if (etat = 'E') then 1* ONLY the extracted values *1

do; select (upcase(type));

1***** first, indicate if variable is num or char *1 when('C' )

do; rc = fput(fid,put(upcase(var),$8.) I I ' $ ');

1***** Then, fill end of line with field position **1 rc fput(fid,put(vc+l,4.) II '-' II

end;

when('Y') do;

rc = end;

when('T' ) do;

rc

end;

otherwise do;

left (put (vc+INT(long) ,4.)));

fput(fid,put(upcase(var) ,$8.) I I '

fput(fid,put(upcase(var) ,$8.) I I ' left (put (vc+int (long),!.)) II '.');

YYMMDD6.') ;

HHMM' II

rc = fput (fid, put (upcase (var J. $8.) II' , ) ;

end;

/***** Then, fill end of line with field position **1 rc fput(fid,put(vc+l,4.) II '-' II

left (put (vc+INT(long) ,4.»); end;

1***** write the whole thing *****1 rc = fwrite(fid); rc = fput(fid,' '); /* prepare for next line *1 vc vc + INT(long);

end; otherwise;

end;

endmethod;

DelFile: /********************************************************************/ 1* DelFile: This routine is used to clean the library after having *1 1* created intermediate files. * I 1* *1 I * usage: call method (' ',' DELFILE' , fichier, extent) ; * I 1********************************************************************1

method fichier $ 1* Name of the file to delete *1 extent $ 1* Extension of the file * I

fdata = ' '; 1***** Verify first if 'fichier'.'extent' exists ..• *****1

954

Page 19: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

if (fileexist(fichier I I '.' I I extent)) then do;

1***** Delete the file *****1 rc filename(fdata,fichier II ' , II extent) ; rc fdelete(fdata); rc filename(fdata,' ');

end;

endmethod;

Verify:

1* ... delete 1* Deassign

*1 *1

/********************************************************************/ 1* Verify: This routine is used to VERIFY the existence of the FTM *1 1* file which would normaly be create by the FOCUS system * I 1* if no problem are encountered during file creation. *1 1* usage: call method('·','VERIFY',fichier,extent,rc); *1 /********************************************************************/

method fichier $ 1* Name of the file to delete */ extent $ /* Extension of the file * / rc 8 /* Return code value: I-file exist, */

drug file

$ $

/* O-file does not. */ / * drug number * I /* file number (study number) */

1***** Verify first if 'fichier'.'extent' exists ... *****/ rc = fileexist(fichier II ' , II extent); if (rc) then

do; end;

else do;

call display('noftmfil.program',fichier,extent,drug,file); end;

endmethod;

/*-========================================================================-*/ array buffer{16} $ 100; PutWrite: /****************************************************************************/ /* PurWrite: This routine writes to a physical file. */ /****************************************************************************/

method fid tab bufferl

optional=buffer2 buffer3 buffer4 bufferS buffer6 buffer7 buffer8 buffer9 bufferl0 bufferll bufferl2 buffer13 buffer14 bufferlS buffer16 ;

1* I: Input variable, 0: Output variable 8 1* I File ID number 8 1* I Tabulation, if needed $ 1* I Character buffer $ /* I Supplementary buffer #2 $ 1* I Supplementary buffer #3 $ /* I Supplementary buffer #4 $ 1* I Supplementary buffer #S $ 1* I Supplementary buffer #6 $ 1* I Supplementary buffer #7 $ /* I Supplementary buffer #8 $ /* I Supplementary buffer #9 $ 1* I Supplementary buffer #10 $ 1* I Supplementary buffer #11 $ /* I Supplementary buffer #12 $ /* I Supplementary buffer #13 $ /* I Supplementary buffer #14 $ / * I Supplementary buffer US $ /* I Supplementary buffer #16

/*** Verify INPUT variables ***1 if bufferl = ' , then

recurn;

do i = 1 to dim(buffer); if buffer{i} AS " then

do; if substr(buffer{i},l,l) = '+' then

do; rc = fput(fid,' '); rc = fwrite(fid); buffer{i} = substr(buffer{i},2);

end; if tab A= . and tab > 2 then

do; rc = fput(fid,repeat(' ',tab-2)); rc fput(fid,buffer{i}); rc fwrite(fid);

end; else

do;

end; end;

rc rc

end;

fput(fid,buffer{i}); fwrite(fid) ;

955

*/ */ */

*1 */ */ */ */ */ *1 */ */ */ */ */ */ */ */ */

Page 20: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

endmethod;

1*-========================================================================-*/

PutWait: 1***************************************************** ***********************/ 1* PutWait: Write to a physical file without the end of line... *1 1**·*********-·*********************-*****-****·****** ***********************/

1* I: Input variable,- 0: Output variable *1 method fid

tab string

8 1* I File ID number *1 8 /* I Tabulation, if needed *1 $ /* I Character string *1

, 1*** Verify INPUT variables ***/ if string =" or string =' , then return;

if tab "= . and tab > 2 then do;

rc rc =

end; else

do; rc =

end; endmethod;

fput(fid,repeat(' ',tab-2»; fput(fid,string);

fput(fid,string);

1*-==================== END o F R 0 UTI N E S=====================-*/

956

Page 21: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

call execcmdi('PRTFILE PORT_PRN; FORMNAME PORTRAIT;'); end;

end; return;

RECTO: select (paper) ;

when('LANDSCAPE') do;

linesize = 132; submit continue;

options ls=132 ps=66; endsubmit; call execcmdi('PRTFILE TOTOLAND; FORMNAME ITALIEN;');

end; otherwise

do; linesize = 112; submit continue;

options ls=112 ps=100; endsubmit; call execcmdi('PRTFILE TOTOPORT; FORMNAME PORTRAIT;');

end; end;

return;

CHK_VAR1: pos = index(seg{i},'\'); if pos A= 0 then substr(seg{i},pos,l)

return;

PROCESS:

if length (filename) else if length(filename) else

> 7 then source1 sourcel

> 7 then source2 source2

/*W***********************************/ /************ PHASE I *************/ /*************************************/

1* Verify WORKING DIRECTORY **1

if workdir do;

rep1 rep2

end;

"'= •• then

workdir; workdir;

, ,. - ,

substr (filename, 1, 7) II filename II '1'; substr (filename, 1, 7) I I filename II "2";

1*** SET Working directory (TYPE) depending on type of data ***1 select (TYPE);

when ( 'ADR') do;

if workdir = " then rep1 = 'Your directory structure for Adverse events';

file1 = 'Your file name for labs'; end;

when ( 'LAB') do;

if workdir = ". then rep1 'Your directory structure for LABS";

file1 = "Your file name for labs"; end;

otherwise do;

if workdir = •• then rep1 = 'Your directory structure for CENTRALIZED data';

file1 = "Your file name for CENTRALIZED"; end;

end;

status = 'Writing'; refresh;

call display('screen',"Extracting FOCUS data.", 'File [" II repl II "J' II file1);

1***** Assigner Ie fichier de reference *****1 call method('routines',"CREATFOC",sourcel,fid,drug,fichier1);

1***** Set default working directory into FOCUS *****1

call method('routines",'PutWrite",fid,l, "VMS SET DEFAULT directory structure', 'SET MORE=OFF', 'DEFINE FILE' II file1);

do i = 1 to dim(seg);

957

Page 22: FILENAME = ECGREAD, SUFFIX = FOC, SEGNAME = … System-based Verification...SAS-based verification of double entry data in a FOCUS® database. Introduction ... Emetic episodes, ...

I I

\ ~

\.

if seg{i} ~= " then

end;

call method('routines','DEFLEN',fid,'E', seg{i},F{i} I I left(put(L{i},best.»);

/***** Fermer la definition des longueurs des champs *****/ rc = fput(fid,'END'); rc = fwrite(fid);

/***** puis DEBUTER l'extraction des variables *****/ rc = fput(fid,'TABLE FILE' II filel); rc = fwrite(fid); vc=O; /* Variable counter */ rc = fput(fid,' PRINT ');

do i = VarStart to dim(seg); if seg{i} ~= " then call method("routines','VAREXT',vc,fid,'E',seg{I});

end;

/****** »> DONT FORGET to insert a line feed. ******/ rc = fput(fid,' '); rc = fwrite(fid);

/***** BY segments VARIABLES *****/ vc = 0; /* Variable counter */

do i = 1 to (VarStart - 1); if seg{i} ~= " then

end;

do; rc = fput(fid,' BY'); call method('routines','VAREXT',vc,fid,'E',seg{i});

end;

rc fput(fid,' ,); rc fwrite{fid); /* CRLF */

if ext cond ~= " then call method('routines','PutWrite',fid,4,ext_cond);

status = 'Extracting'; refresh;

/***** Save file into 'file.FEX' where file is GIVEN by user *****/ call method('routines','SAVEFOC',sourcel,fid); rc = sysrc(); if (rc) then call display('exit');

/***** SUBMIT the FOCUS file *****1 /*********************************/ rc = system ( 'FOCUS EX' , II sourcel II "'); call method('routines.scl', 'VERIFY' ,sourcel, 'FTM' ,rc,drug,fichierl);

1*** if the focus file is not created then EXIT ***/ if (rc = 0) then return;

status 'Processing'; refresh;

1************************************·/ /************ PHASE II ************/ 1********************'****************/

/*** /***

SET Working directory (TYPE) depending on type of data ***/ rep2 and file2 are set here ***/

status = 'Writing'; refresh;

call display('screen','Extracting FOCUS data.', 'File [' II rep2 II 'J" II file2);

/***** Assigner Ie fichier de reference *****/ call method("routines','CREATFOC',

source2,fid,drug,fichier2);

/***** Set default working directory into FOCUS *****1

call method("routines', "PutWrite',fid,l, "VMS SET DEFAULT directory structure", "SET MORE=OFF', 'DEFINE FILE' II file2);

958