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.  
 |