home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MAGAZINE / MISC / ITPSEP90.ZIP / WRITEDBF.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1990-09-04  |  11.5 KB  |  384 lines

  1. UNIT WriteDbf; {$R-}
  2.  
  3. {***************************************************************
  4. **   UNIT   : WriteDBF.PAS                                    **
  5. **   PURPOSE: Write records to dBASE III+/IV DBF files        **
  6. ****************************************************************}
  7.  
  8. INTERFACE
  9.  
  10. USES Dos,Crt;
  11.  
  12. {-------------------------------------------------
  13. - Create types and define variables              -
  14. -------------------------------------------------}
  15.  
  16. TYPE
  17.  
  18.   DbfFieldType = RECORD
  19.     FdName   : String[10];
  20.     FdType   : Char;
  21.     FdLength : Byte;
  22.     FdDec    : Byte;
  23.   END;
  24.  
  25.   DbfFieldTypeA = ARRAY[0..0] OF DbfFieldType;
  26.  
  27.   DbfFileType = RECORD
  28.     VersionNumber : Byte;
  29.     Update        : ARRAY [1..3] OF Byte;
  30.     NbrRec        : Longint;
  31.     HdrLen        : Integer;
  32.     RecLen        : Word;
  33.     NbrFlds       : Integer;
  34.     FileSize      : Longint;
  35.     FileHndl      : FILE;
  36.     FileName      : String[12];
  37.     FieldStru     : ^DbfFieldTypeA;
  38.   END;
  39.  
  40.   DbfFile = ^DbfFileType;
  41.   CharArray = ARRAY[0..0] OF Char;
  42.   CharPtr = ^CharArray;
  43.  
  44. FUNCTION DbfOpen(FileName : String): DbfFile;
  45. FUNCTION DbfClose(D: DbfFile): Boolean;
  46. FUNCTION DbfReadHdr(D: DbfFile): Byte;
  47. PROCEDURE DbfDispHdr(D: DbfFile);
  48. PROCEDURE Pause;
  49. FUNCTION DbfReadStru(D: DbfFile): Boolean;
  50. FUNCTION DbfInputRec(D: DbfFile): CharPtr;
  51. PROCEDURE DbfWriteRec (RecNum: Longint; D: DbfFile; P: CharPtr);
  52.  
  53. {***************************************************************}
  54.                         IMPLEMENTATION
  55. {***************************************************************}
  56.  
  57. PROCEDURE Tab(Col:Byte);
  58. BEGIN
  59.   GotoXY(Col MOD 80,WhereY)
  60. END;
  61.  
  62. {-------------------------------------------------
  63. - Name   : HeapFunc                              -
  64. - Purpose: Provide heap error handling           -
  65. - Input  : Size of memory request to heap        -
  66. - Output : Error return code                     -
  67. -------------------------------------------------}
  68.  
  69. {$F+} FUNCTION HeapFunc(Size: Word) : Integer; {$F-}
  70. BEGIN
  71.   HeapFunc := 1  {Return Nil when can not complete request}
  72. END;
  73.  
  74. {-------------------------------------------------
  75. - Name   : DbfOpen                               -
  76. - Purpose: Manage open DBF file tasks            -
  77. - Input  : Filename stored in a string           -
  78. - Output : Pointer to a new DbfFileType record   -
  79. -------------------------------------------------}
  80.  
  81. FUNCTION DbfOpen(FileName : String): DbfFile;
  82. VAR
  83.    D : DbfFile;
  84. BEGIN
  85.    GetMem(D,SizeOf(DbfFileType));
  86.    D^.FileName := FileName;
  87.    Assign(D^.FileHndl, FileName);
  88.    Reset(D^.FileHndl,1);             {Set record length to 1}
  89.    DbfOpen := D;
  90. END;
  91.  
  92. {-------------------------------------------------
  93. - Name   : DbfClose                              -
  94. - Purpose: Closes an open dBASE file             -
  95. - Input  : Pointer to record of DbfFileType      -
  96. - Output : True upon file close                  -
  97. -------------------------------------------------}
  98.  
  99. FUNCTION DbfClose(D: DbfFile): Boolean;
  100. BEGIN
  101.   Close(D^.FileHndl);
  102.   FreeMem(D^.FieldStru, SizeOf(DbfFieldType)*(D^.NbrFlds+1));
  103.   FreeMem(D,SizeOf(DbfFileType));
  104.   DbfClose := TRUE
  105. END;
  106.  
  107. {-------------------------------------------------
  108. - Name   : DbfReadHdr                            -
  109. - Purpose: Read the Dbase file header info       -
  110. -          and store it in the header record     -
  111. - Input  : Pointer to record of DbfFileType      -
  112. - Output : Result code from reading header       -
  113. -------------------------------------------------}
  114.  
  115. FUNCTION DbfReadHdr(D: DbfFile): Byte;
  116.  
  117. TYPE
  118.    DbfHdrMask = RECORD
  119.       VersionNumber : Byte;
  120.       Update        : ARRAY [1..3] OF Byte;
  121.       NbrRec        : Longint;
  122.       HdrLen        : Integer;
  123.       RecLen        : Integer;
  124.       Reserved      : ARRAY [1..20] OF Char;
  125.    END;
  126. VAR
  127.   Result : Word;
  128.   H : DbfHdrMask;
  129.   I : Byte;
  130. BEGIN
  131.   Seek(D^.FileHndl,0);              {Move ptr to file beginning}
  132.   BlockRead(D^.FileHndl, H, SizeOf(H), Result); {Read hdr info}
  133.   IF SizeOf(H) = Result THEN
  134.     BEGIN
  135.       WITH D^ DO
  136.         BEGIN
  137.           VersionNumber := H.VersionNumber  AND 7;
  138.           FOR I := 1 TO 3 DO
  139.             Update[I] := H.Update[I];
  140.           NbrRec := H.NbrRec;
  141.           HdrLen := H.HdrLen;
  142.           RecLen := H.RecLen;
  143.           NbrFlds := (H.HdrLen - 33) DIV 32;
  144.           FileSize := H.HdrLen + H.RecLen * H.NbrRec + 1;
  145.           DbfReadHdr := 0;                  {No errors        }
  146.           IF VersionNumber <> 3 THEN
  147.             DbfReadHdr := 1                 {Not a dBase file }
  148.           ELSE
  149.             IF NbrRec = 0 THEN
  150.               DbfReadHdr := 2               {No records       }
  151.         END {WITH}
  152.     END {IF}
  153.   ELSE
  154.     DbfReadHdr := 3;                        {Error reading Dbf}
  155. END; {FUNCTION}
  156.  
  157. {-------------------------------------------------
  158. - Name   : DbfDispHdr                            -
  159. - Purpose: Display the header info to the screen -
  160. - Input  : Pointer to a record of DbfFileType    -
  161. -------------------------------------------------}
  162.  
  163. PROCEDURE DbfDispHdr(D: DbfFile);
  164.  
  165. BEGIN
  166.   WITH D^ DO
  167.     BEGIN
  168.       WriteLn('Using ',FileName); WriteLn;
  169.       WriteLn('dBASE Version         :', VersionNumber:8);
  170.       WriteLn('Number of data records:', NbrRec:8);
  171.       Write('Date of last update   : ');
  172.       WriteLn(Update[2]:2,'/',Update[3], '/',Update[1]);
  173.       WriteLn('Header length         :', HdrLen:8);
  174.       WriteLn('Record length         :', RecLen:8);
  175.       WriteLn('Number of fields      :', NbrFlds:8);
  176.       WriteLn('File size             :', FileSize:8)
  177.     END
  178. END;
  179.  
  180. {-------------------------------------------------
  181. - Name   : Pause                                 -
  182. - Purpose: Print msg and prompt use for keypress -
  183. -------------------------------------------------}
  184.  
  185. PROCEDURE Pause;
  186.  
  187. BEGIN
  188.   WriteLn;
  189.   WriteLn('Press Enter to continue');
  190.   ReadLn;
  191. END;
  192.  
  193. {-------------------------------------------------
  194. - Name   : DbfReadStru                           -
  195. - Purpose: Read file structure & store in dBASE  -
  196. -          file header record                    -
  197. - Input  : Pointer to record of DbfFileType      -
  198. - Output : Boolean success response              -
  199. -------------------------------------------------}
  200.  
  201. FUNCTION DbfReadStru(D: DbfFile): Boolean;
  202.  
  203. TYPE
  204.   DbfFieldMask = RECORD
  205.     FdName    : ARRAY [1..11] OF Char;
  206.     FdType    : Char;
  207.     Reserved1 : ARRAY [1..4] OF Char;
  208.     FdLength  : Byte;
  209.     FdDec     : Byte;
  210.     Reserved2 : ARRAY [1..14] OF Char;
  211.   END;
  212.  
  213. VAR
  214.   Result : Word;
  215.   I, J, HdrTerminator : Byte;
  216.   FldTmp : DbfFieldMask;
  217.  
  218. BEGIN
  219.  
  220.   GetMem(D^.FieldStru, SizeOf(DbfFieldType)*(D^.NbrFlds+1));
  221.  
  222.  {Set up record status field}
  223.  
  224.   WITH DbfFieldType(D^.FieldStru^[0]) DO BEGIN
  225.     FdName   := 'RecStatus  ';
  226.     FdType   := 'C';
  227.     FdLength := 1;
  228.     FdDec    := 0
  229.     END;
  230.  
  231.   FOR I := 1 TO D^.NbrFlds DO BEGIN
  232.     BlockRead(D^.FileHndl,FldTmp,SizeOf(FldTmp), Result);
  233.     WITH DbfFieldType(D^.FieldStru^[I]) DO BEGIN
  234.       J := POS(#0,FldTmp.FdName);
  235.       IF J <> 0 THEN FdName := Copy(FldTmp.FdName,1,J-1);
  236.       FdType := FldTmp.FdType;
  237.       Write(FdType);
  238.       FdLength := FldTmp.FdLength;
  239.       FdDec    := FldTmp.FdDec
  240.       END
  241.     END;
  242.  
  243.   {Last Hdr Byte}
  244.  
  245.   BlockRead(D^.FileHndl,HdrTerminator,1,Result);
  246.   IF HdrTerminator <> 13 THEN
  247.     DbfReadStru := FALSE          {Bad Dbf header}
  248.   ELSE
  249.     DbfReadStru := TRUE
  250. END;
  251.  
  252. {-------------------------------------------------
  253. - Name   : DbfInputRec                           -
  254. - Purpose: Get a record from user                -
  255. - Input  : Pointer to DbfFileType record         -
  256. - Output : Pointer to buffer to write to file    -
  257. -------------------------------------------------}
  258.  
  259. FUNCTION DbfInputRec(D: DbfFile): CharPtr;
  260. VAR
  261.   S : String[255];
  262.   DbfPtr : CharPtr;
  263.   FPos,TempPos : Integer;
  264.   I : Integer;
  265.  
  266. BEGIN
  267.  
  268.   GetMem(DbfPtr,D^.RecLen);    {Reserve mem for Record contents}
  269.   IF DbfPtr = NIL THEN BEGIN   {Memory allocation error        }
  270.     DbfInputRec := NIL;
  271.     Exit
  272.     END;
  273.  
  274.   FillChar(DbfPtr^,D^.RecLen,' ');      {Pad record with spaces}
  275.  
  276.   ClrScr;
  277.   GotoXY(33,1);
  278.   WriteLn('Enter records'); WriteLn;
  279.   Write('Field Name    Type                Length');
  280.   WriteLn('  Decimals  - Enter Value');
  281.   WriteLn;
  282.  
  283.   FPos := 1; {Set current position in rec to write to next field}
  284.   FOR I := 1 TO D^.NbrFlds DO BEGIN
  285.  
  286.   {Input the value from the user}
  287.  
  288.     WITH DbfFieldType(D^.FieldStru^[I]) DO BEGIN
  289.       IF FdType = 'M' THEN BEGIN
  290.          END
  291.       ELSE BEGIN
  292.         Write(FdName);Tab(15);
  293.         Write(FdType);
  294.         CASE FdType OF
  295.           'C' : Write('Character       ');
  296.           'N' : Write('Numeric         ');
  297.           'F' : Write('Floating Point  ');
  298.           'L' : Write('Logical         ');
  299.           'D' : Write('Date (YYYYMMDD) ')
  300.           ELSE
  301.         END;
  302.         Write(FdLength:8,FdDec:8);Tab(54);Write('<');
  303.         FillChar(S[1], FdLength, ' ');
  304.         S[0] := Chr(FdLength);
  305.         Write(S,'>');
  306.         GotoXY(WhereX-FdLength-1,WhereY);
  307.         ReadLn(S);
  308.  
  309.         {Truncate if too long}
  310.  
  311.         IF Length(S) > FdLength THEN S := Copy(S,1,FdLength);
  312.  
  313.   {Put the field contents into the buffer, adjust position you
  314.    begin writing to make field value left or right justified}
  315.  
  316.         CASE FdType OF                                 {Justify }
  317.           'C','L','D': TempPos := FPos;                {   Left }
  318.           ELSE TempPos := FPos + FdLength - Length(S)  {or Right}
  319.           END;  {CASE}
  320.         Move(S[1],DbfPtr^[TempPos],Length(S));
  321.         END;  {IF}
  322.  
  323.         Inc(FPos,FdLength)       {set to beginning of next field}
  324.  
  325.       END  {WITH}
  326.     END;  {FOR}
  327.     DbfInputRec := DbfPtr
  328.   END; {BEGIN}
  329.  
  330. {-------------------------------------------------
  331. - Name   : DbfWriteRec                           -
  332. - Purpose: Write a dBASE record                  -
  333. - Input  : Record number to write                -
  334. -          Pointer to DbfFileType record         -
  335. -          Pointer to record buffer to write     -
  336. - Output :                                       -
  337. -------------------------------------------------}
  338.  
  339. PROCEDURE DbfWriteRec (RecNum: Longint; D: DbfFile; P: CharPtr);
  340.  
  341. VAR
  342.   Offset,RecPos : Longint;
  343.   Appending : Boolean;
  344.   EofChar : Char;
  345.   Y,M,Day,Dow : Word;
  346.   Date : String[3];
  347. BEGIN
  348.   WITH D^ DO BEGIN
  349.     IF RecNum = -1 THEN BEGIN                  {Appending RECORD}
  350.       Offset := NbrRec * RecLen;          {Calc offset into data}
  351.       Inc(NbrRec);                   {Add a record for Appending}
  352.       Seek(FileHndl,4); {Update the hdr field value # of records}
  353.       BlockWrite(FileHndl,NbrRec,Integer(SizeOf(NbrRec)));
  354.       Appending := TRUE
  355.       END
  356.     ELSE BEGIN                        {Replacing existing RECORD}
  357.       Offset := (RecNum - 1) * RecLen;    {Calc offset into data}
  358.       Appending := FALSE
  359.       END;
  360.     RecPos := Offset + HdrLen;        {Calc offset into FILE}
  361.     Seek(FileHndl,RecPos);          {Position to record location}
  362.     BlockWrite(FileHndl,P^,RecLen);
  363.     FreeMem(P,RecLen);
  364.  
  365.     IF Appending THEN BEGIN    {Write EOF character if Appending}
  366.       EofChar := Chr(26);
  367.       BlockWrite(FileHndl,EofChar,1)
  368.       END;
  369.  
  370.     GetDate(Y,M,Day,Dow);{Update last update date in file header}
  371.     {Create Date}
  372.     Date := Chr(Lo(Y-1900)) + Chr(Lo(M)) + Chr(Lo(Day));
  373.     Seek(FileHndl,1);
  374.     BlockWrite(FileHndl,Date[1],3);
  375.  
  376.     WriteLn('Record written and file updated'); WriteLn;
  377.  
  378.     END  {WITH}
  379.   END;  {DbfWriteRec}
  380.  
  381.   BEGIN
  382.   HeapError := @HeapFunc;         {Initialize HeapError FUNCTION}
  383. END.
  384.