Contributor: SWAG SUPPORT TEAM unit dbaseiii; { unit including procedures for accessing DBaseIII files} interface uses Crt; Procedure OpenDBFData; Procedure OpenDBFMemo; Procedure ReadDBFRecord(I : Longint); Procedure WriteDBFRecord; Procedure ReadDBFMemo(BlockNumber : integer); Procedure WriteDBFMemo(var BlockNumberString : string); Procedure CloseDBFData; Procedure CloseDBFMemo; const DBFMaxRecordLength = 4096; DBFMemoBlockLength = 512; DBFMaxMemoLength = 4096; type DBFHeaderRec = Record HeadType : byte; Year : byte; Month : byte; Day : byte; RecordCount : longint; HeaderLength : integer; RecordSize : integer; Garbage : array[1..20] of byte; end; type DBFFieldRec = Record FieldName : array[1..11] of char; FieldType : char; Spare1, Spare2 : integer; Width : byte; Dec : byte; WorkSpace : array[1..14] of byte; end; var DBFFileName : string; DBFDataFile : File; DBFDataFileAvailable : boolean; DBFBuffer : array [1..DBFMaxRecordLength] of char; DBFHeading : DBFHeaderRec; DBFField : DBFFieldRec; DBFFieldCount : integer; DBFFieldContent : array [1..128] of string; DBFNames : array [1..128] of string[10]; DBFLengths : array [1..128] of byte; DBFTypes : array [1..128] of char; DBFDecimals : array [1..128] of byte; DBFContentStart : array [1..128] of integer; DBFMemoFile : File; DBFMemoFileAvailable : boolean; DBFMemoBuffer : Array [1..DBFMemoBlockLength] of byte; DBFMemo : Array [1..DBFMaxMemoLength] of char; DBFMemoLength : integer; DBFMemoEnd : boolean; DBFMemoBlock : integer; DBFDeleteField : char; DBFFieldStart : integer; DBFRecordNumber : longint; (****************************************************************) implementation (****************************************************************) Procedure ReadDBFHeader; var RecordsRead : integer; begin BlockRead (DBFDataFile, DBFHeading, SizeOf(DBFHeading), RecordsRead); end; (*****************************************************************) Procedure ProcessField (F : DBFFieldRec; I : integer); var J : integer; begin with F do begin DBFNames [I] := ''; J := 1; while (J<11) and (FieldName[J] <> #0) do begin DBFNames[I] := DBFNames[I] + FieldName [J]; J := J + 1; end; DBFLengths [I] := Width; DBFTypes [I] := FieldType; DBFDecimals [I] := Dec; DBFContentStart [I] := DBFFieldStart; DBFFieldStart := DBFFieldStart + Width; end; end; (***************************************************************) Procedure ReadFields; var I : integer; RecordsRead : integer; begin Seek(DBFDataFile,32); I := 1; DBFFieldStart := 2; DBFField.FieldName[1] := ' '; while (DBFField.FieldName[1] <> #13) do begin BlockRead(DBFDataFile,DBFField.FieldName[1],1); if (DBFField.FieldName[1] <> #13) then begin BlockRead(DBFDataFile, DBFField.FieldName[2],SizeOf(DBFField) - 1, RecordsRead); ProcessField (DBFField, I); I := I + 1; end; end; DBFFieldCount := I - 1; end; (***********************************************************) Procedure OpenDBFData; begin DBFDataFileAvailable := false; Assign(DBFDataFile, DBFFileName+'.DBF'); {$I-} Reset(DBFDataFile,1); If IOResult<>0 then exit; {$I+} DBFDataFileAvailable := true; Seek(DBFDataFile,0); ReadDBFHeader; ReadFields; end; (******************************************************************) Procedure CloseDBFData; begin if DBFDataFileAvailable then Close(DBFDataFile); end; (*******************************************************************) Procedure OpenDBFMemo; begin DBFMemoFileAvailable := false; Assign(DBFMemoFile, DBFFileName+'.DBT'); {$I-} Reset(DBFMemoFile,1); If IOResult<>0 then exit; {$I+} DBFMemoFileAvailable := true; Seek(DBFMemoFile,0); end; (*******************************************************************) Procedure CloseDBFMemo; begin If DBFMemoFileAvailable then close(DBFMemoFile); end; (*******************************************************************) Procedure GetDBFFields; var I : byte; J : integer; Response : string; begin DBFDeleteField := DBFBuffer[1]; For I:=1 to DBFFieldCount do begin DBFFieldContent[I] := ''; For J := DBFContentStart[I] to DBFContentStart [I] + DBFLengths[I] -1 do DBFFieldContent[I] := DBFFieldContent[I] + DBFBuffer[J]; For J := 1 to DBFLengths[I] do if DBFFieldContent[J]=#0 then DBFFieldContent[J]:=#32; end; end; (***********************************************************************) Procedure ReadDBFRecord (I : Longint); var RecordsRead : integer; begin Seek(DBFDataFile, DBFHeading.HeaderLength + DBFHeading.RecordSize * (I - 1)); BlockRead (DBFDataFile, DBFBuffer, DBFHeading.RecordSize, RecordsRead); GetDBFFields; end; (**********************************************************************) Procedure ReadDBFMemo(BlockNumber : integer); var I : integer; RecordsRead : word; begin DBFMemoLength := 0; DBFMemoEnd := false; If not DBFMemoFileAvailable then begin DBFMemoEnd := true; exit; end; FillChar(DBFMemo[1],DBFMaxMemoLength,#0); Seek(DBFMemoFile,BlockNumber*DBFMemoBlockLength); repeat BlockRead(DBFMemoFile,DBFMemoBuffer,DBFMemoBlockLength,RecordsRead); For I := 1 to RecordsRead do begin DBFMemoLength := DBFMemoLength + 1; DBFMemo[DBFMemoLength] := chr(DBFMemoBuffer[I] and $7F); If (DBFMemoBuffer[I] = $1A) or (DBFMemoBuffer[I] = $00) then begin DBFMemoEnd := true; DBFMemoLength := DBFMemoLength - 1; exit; end; end; until DBFMemoEnd; end; (*********************************************************************) Procedure WriteDBFMemo {(var BlockNumberString : string)}; var K : integer; ReturnCode : integer; begin Val(BlockNumberString,DBFMemoBlock,ReturnCode); If ReturnCode>0 then DBFMemoBlock := 0; If DBFMemoBlock>0 then begin Writeln; ReadDBFMemo(DBFMemoBlock); If DBFMemoLength=0 then exit; For K := 1 to DBFMemoLength do Write(DBFMemo[K]); WriteLn; end; end; (****************************************************************) Procedure WriteDBFRecord; var J : byte; begin For J := 1 to DBFFieldCount do begin Write(DBFNames[J]); GoToXY(12,J); WriteLn(DBFFieldContent[J]); if DBFTypes[J]='M' then WriteDBFMemo(DBFFieldContent[J]); end; end; (*******************************************************************) begin end.