home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / WIN_UTL1 / DB4PK1.ZIP / PACKTABL.BAS < prev    next >
BASIC Source File  |  1994-02-10  |  10KB  |  346 lines

  1.  
  2. 'Sub PackTable Packs dBASE IV tables.
  3. 'Use Freely in your applications but use at your own risk.
  4. 'Comments are welcome to Darryl Buchanan (CompuServe 71435,1442)
  5. '
  6. 'Visual Basic 3.0 does not provide a Pack function for dBASE IV
  7. 'tables!  I wrote this function for my own applications to
  8. 'provide such a capability.  It works with dBASE IV (.DBF) files
  9. 'with maintained indexes (.MDX) and with attached memo (.DBT)
  10. 'files.
  11. '
  12. 'This subroutine works in the following fashion:
  13. '1. Delete any pre-existing temp files:
  14. '   (XXXXXXXX.DBF, XXXXXXXX.DBT, or XXXXXXXX.MDX)
  15. '2. Read the old tables field and index descriptions.
  16. '3. Rename the existing files to XXXXXXXX.*
  17. '   (NOTE:  dBASE IV tables with .MDX indexes maintain
  18. '   the original table name in the index header.  That's
  19. '   why we first rename the old file to xxxxxxxx.* and
  20. '   create the new file with the original name.  Visual
  21. '   Basics database engine can read the file ok with the
  22. '   new xxxxxxxx name, but Paradox for Windows chokes and
  23. '   says the index is corrupt.  Go figure.  Anyway, doing
  24. '   it this way keeps the right table name in the .MDX file
  25. '   so Paradox is happy.  I don't work with dBASE IV for
  26. '   DOS so I can't guarantee dBASE IV will be happy with
  27. '   the new files.  I'd appreciate it if someone could
  28. '   tell me if dBASE IV is happy with a file packed with
  29. '   this application.  It works with Visual Basic and
  30. '   Paradox for Windows applications.)
  31. '4. Create a new table and index with the same layout.
  32. '5. Read all the records from the old table and write them
  33. '   to the new table.  This skips all the deleted records.
  34. '6. Delete the old table.
  35. '
  36. 'This function requires 2 parameters:
  37. ' sDatabaseName contains the directory where your database
  38. '    resides.  For example:  "C:\MYDBDIR"
  39. ' sTableName contains the name of your table (does not include
  40. '    the .DBF extension).  For example:  "MYTABLE"
  41. '
  42. 'An example implementation is the following code attached
  43. 'to a button that calls this function.  txtDatabase and
  44. 'txtTable are two text fields on a form where the user has
  45. 'entered a database directory and table name respectively.
  46. '
  47. 'Sub cmdPack_Click ()
  48. '    Dim sDatabase As String
  49. '    Dim sTable As String
  50. '    sDatabase = txtDatabase.Text
  51. '    sTable = txtTable.Text
  52. '    Call PackTable(sDatabase, sTable)
  53. 'End Sub
  54. '
  55. 'Warning!!!  This routine works by copying all the records
  56. 'from your old file to a new file.  Therefore you must have
  57. 'enough room on your drive to hold a copy of your original file.
  58. 'The new file will be less than or equal to in size to your old
  59. 'file.  You must also have exclusive access to your table.
  60. 'I have set the database open to exclusive mode to ensure this.
  61. 'That means the best (and only) time to run this is when
  62. 'noone else is accessing the database.
  63. '
  64. 'WARNING!!! IT IS ALWAYS A GOOD IDEA TO BACK UP YOUR DATAFILES
  65. 'BEFORE YOU TRY SOMETHING LIKE THIS.  IT NECESSARILY READS AND
  66. 'WRITES EVERY RECORD IN YOUR TABLE.  IT ALSO RENAMES FILES
  67. 'A COUPLE OF TIMES.  IF YOUR SYSTEM GLITCHES IN THE MIDDLE OF
  68. 'THIS OPERATION YOU COULD BE HUNG OUT TO DRY WITHOUT A BACKUP.
  69. 'USE THIS AT YOUR OWN RISK!!!!!!!!!!!
  70. '
  71. Sub PackTable (sDatabaseName As String, sTableName As String)
  72.  
  73. Dim tblNew      As Table
  74. Dim tblOld      As Table
  75. Dim tdfNew      As New TableDef
  76. Dim tdfOld      As New TableDef
  77. Dim dbDatabase  As Database
  78. Dim idxNew      As New Index
  79.  
  80. Dim iIndex          As Integer
  81. Dim iCountFields    As Integer
  82. Dim iCountIndexes   As Integer
  83.  
  84. Dim sDBFFile As String
  85. Dim sDBTFile As String
  86. Dim sMDXFile As String
  87. Dim sTmpDBFFile As String
  88. Dim sTmpDBTFile As String
  89. Dim sTmpMDXFile As String
  90.  
  91. 'Put up a busy hourglass.
  92. screen.MousePointer = 11
  93.  
  94. 'Build the complete file names.
  95. If Right$(sDatabaseName, 1) = "\" Then
  96.     sDBFFile = sDatabaseName + sTableName
  97.     sTmpDBFFile = sDatabaseName + "XXXXXXXX"
  98. Else
  99.     sDBFFile = sDatabaseName + "\" + sTableName
  100.     sTmpDBFFile = sDatabaseName + "\XXXXXXXX"
  101. End If
  102. sDBTFile = sDBFFile + ".DBT"
  103. sMDXFile = sDBFFile + ".MDX"
  104. sTmpDBTFile = sTmpDBFFile + ".DBT"
  105. sTmpMDXFile = sTmpDBFFile + ".MDX"
  106. sTmpDBFFile = sTmpDBFFile + ".DBF"
  107. sDBFFile = sDBFFile + ".DBF"
  108.  
  109. 'Kill any existing temporary tables
  110. 'Kill XXXXXXXX.DBF
  111. On Error GoTo NoXXXDBF
  112. 'MsgBox sTmpDBFFile, 0, "DEBUG - Killing:"
  113. Kill sTmpDBFFile
  114. GoTo XXXDBT
  115.  
  116. NoXXXDBF:
  117. On Error GoTo 0
  118. Resume XXXDBT
  119.  
  120. XXXDBT:
  121. 'Kill XXXXXXXX.DBT
  122. On Error GoTo NoXXXDBT
  123. 'MsgBox sTmpDBTFile, 0, "DEBUG - Killing"
  124. Kill sTmpDBTFile
  125. GoTo XXXMDX
  126.  
  127. NoXXXDBT:
  128. On Error GoTo 0
  129. Resume XXXMDX
  130.  
  131. XXXMDX:
  132. 'Kill XXXXXXXX.MDX
  133. On Error GoTo NoXXXMDX
  134. 'MsgBox sTmpMDXFile, 0, "DEBUG - Killing"
  135. Kill sTmpMDXFile
  136. GoTo EndXXX
  137.  
  138. NoXXXMDX:
  139. On Error GoTo 0
  140. Resume EndXXX
  141.  
  142. EndXXX:
  143. On Error GoTo 0
  144. '***** FINISHED DELETING EXISTING TEMP FILES ****
  145.  
  146. 'Open the database.
  147. 'Open for exclusive use.  You will get an error here if someone
  148. 'already has the table open.  You can add some error checking
  149. 'here if you want.
  150. Set dbDatabase = OpenDatabase(sDatabaseName, True, False, "dBASE IV;")
  151.  
  152. 'Get table definition of the table.
  153. Set tdfOld = dbDatabase.TableDefs(sTableName)
  154.  
  155. 'Define fields - Get number of fields in table.
  156. iCountFields = tdfOld.Fields.Count
  157.  
  158. 'Set up an array of fields. (The array is 0 based.  Adjust
  159. 'the field count down by 1 for this.)
  160. iCountFields = iCountFields - 1
  161.  
  162. 'Use ReDim to dynamically size the array.  That way you don't
  163. 'have to arbitrarily set a maximum number of fields.
  164. ReDim afldNewFields(iCountFields) As New field
  165.  
  166. 'Now loop through all the field definitions of the old
  167. 'file and assign them to the new file.
  168. For iIndex = 0 To iCountFields
  169.     afldNewFields(iIndex).Name = tdfOld.Fields(iIndex).Name
  170.     afldNewFields(iIndex).Type = tdfOld.Fields(iIndex).Type
  171.     afldNewFields(iIndex).Size = tdfOld.Fields(iIndex).Size
  172.     afldNewFields(iIndex).Attributes = tdfOld.Fields(iIndex).Attributes
  173.     'The OrdinalPosition, SourceField, SourceTable, and Value
  174.     'properties do not get set when you are creating the
  175.     'table.  They are only valid when this is part of a
  176.     'recordset.
  177. Next
  178.  
  179. 'Now duplicate the indexes.
  180. iCountIndexes = tdfOld.Indexes.Count
  181. 'Adjust the count back one because the array is 0 based.
  182. iCountIndexes = iCountIndexes - 1
  183. If (iCountIndexes < 0) Then
  184.     MsgBox "There Are No Indexes Defined!", 0, "Warning!"
  185.     GoTo NoIndexes
  186. End If
  187.  
  188. 'Use ReDim to dynamically size the array.  That way you don't
  189. 'have to arbitrarily set a maximum number of indexes.
  190. ReDim aidxNewIndexes(iCountIndexes) As New Index
  191.  
  192. For iIndex = 0 To iCountIndexes
  193.     aidxNewIndexes(iIndex).Fields = tdfOld.Indexes(iIndex).Fields
  194.     aidxNewIndexes(iIndex).Name = tdfOld.Indexes(iIndex).Name
  195.     aidxNewIndexes(iIndex).Unique = tdfOld.Indexes(iIndex).Unique
  196.     aidxNewIndexes(iIndex).Primary = tdfOld.Indexes(iIndex).Primary
  197. Next
  198.  
  199. NoIndexes:
  200.  
  201. dbDatabase.Close
  202.  
  203. '**********************************************
  204. 'Rename all the existing files to the TEMP file
  205. 'names.  Then re-open the database.
  206. '**********************************************
  207. On Error GoTo NorDBFFile
  208. Name sDBFFile As sTmpDBFFile
  209. On Error GoTo 0
  210. GoTo lblrMDXFile
  211. NorDBFFile:
  212. On Error GoTo 0
  213. MsgBox "Error Renaming .DBF File to XXXXXXXX.DBF", 0, "ERROR!"
  214. Resume lblrMDXFile
  215.  
  216. lblrMDXFile:
  217. On Error GoTo NorMDXFile
  218. Name sMDXFile As sTmpMDXFile
  219. On Error GoTo 0
  220. GoTo lblrDBTFile
  221.  
  222. NorMDXFile:
  223. On Error GoTo 0
  224. MsgBox "Error Renaming .MDX File to XXXXXXXX.MDX", 0, "ERROR!"
  225. Resume lblrDBTFile
  226.  
  227. lblrDBTFile:
  228. On Error GoTo NorDBTFile
  229. Name sDBTFile As sTmpDBTFile
  230. On Error GoTo 0
  231. 'Don't put up a warning here, there might not be an
  232. 'original .DBT file.
  233. GoTo EndOfRename
  234.  
  235. NorDBTFile:
  236. On Error GoTo 0
  237. Resume EndOfRename
  238.  
  239. EndOfRename:
  240. '***** FINISHED RENAMING EXISTING FILES *****
  241.  
  242. 'Re-Open the database.
  243. 'Open for exclusive use.  You will get an error here if someone
  244. 'already has the table open.  You can add some error checking
  245. 'here if you want.
  246. Set dbDatabase = OpenDatabase(sDatabaseName, True, False, "dBASE IV;")
  247. 'Now we have all the fields.
  248. 'Build the new tabledef.
  249. 'Set the name of the new table.
  250. tdfNew.Name = sTableName
  251. 'Now append the fields to the table definition.
  252. For iIndex = 0 To iCountFields
  253.     tdfNew.Fields.Append afldNewFields(iIndex)
  254. Next
  255.  
  256. 'Now append the indexes to the new table.
  257. If iCountIndexes >= 0 Then
  258.     For iIndex = 0 To iCountIndexes
  259.         tdfNew.Indexes.Append aidxNewIndexes(iIndex)
  260.     Next
  261. End If
  262.  
  263. 'Now append the new table to the database
  264. dbDatabase.TableDefs.Append tdfNew
  265.  
  266. 'Open the new temporary table.
  267. 'NOTE:  I don't have any error checking on these opens.
  268. Set tblOld = dbDatabase.OpenTable("XXXXXXXX")
  269. '3 = DenyRead and DenyWrite to others.
  270. Set tblNew = dbDatabase.OpenTable(sTableName, 3)
  271. 'Copy records from old to new
  272. 'Set order
  273. tblOld.Index = ""
  274. tblNew.Index = ""
  275. 'Make sure there are records.
  276. If tblOld.RecordCount < 1 Then
  277.     GoTo NoRecords
  278. End If
  279. tblOld.MoveFirst
  280. Do
  281.     'Keep going until you get to the end of the file.
  282.     If tblOld.EOF Then
  283.         Exit Do
  284.     End If
  285.     'Add a new record to the new table.
  286.     tblNew.AddNew
  287.     'Now put in all the data.
  288.     For iIndex = 0 To iCountFields
  289.         tblNew(tdfOld.Fields(iIndex).Name) = tblOld(tdfOld.Fields(iIndex).Name)
  290.     Next
  291.     'Now update the record.
  292.     tblNew.Update
  293.     'Get the next old record.
  294.     tblOld.MoveNext
  295. Loop
  296.  
  297. NoRecords:
  298.  
  299. 'Close all the files.
  300. tblOld.Close
  301. tblNew.Close
  302. dbDatabase.Close
  303.  
  304. 'Delete all the old files.
  305. On Error GoTo NoDBFFile
  306. Kill sTmpDBFFile
  307. On Error GoTo 0
  308. GoTo lblMDXFile
  309. NoDBFFile:
  310. On Error GoTo 0
  311. MsgBox "Error Deleting .DBF File", 0, "ERROR!"
  312. Resume lblMDXFile
  313.  
  314. lblMDXFile:
  315. On Error GoTo NoMDXFile
  316. Kill sTmpMDXFile
  317. On Error GoTo 0
  318. GoTo lblDBTFile
  319.  
  320. NoMDXFile:
  321. On Error GoTo 0
  322. MsgBox "Error Deleting .MDX File", 0, "ERROR!"
  323. Resume lblDBTFile
  324.  
  325. lblDBTFile:
  326. On Error GoTo NoDBTFile
  327. Kill sTmpDBTFile
  328. On Error GoTo 0
  329. 'Don't put up a warning here, there might not be an
  330. 'original .DBT file.
  331. GoTo EndOfSub
  332.  
  333. NoDBTFile:
  334. On Error GoTo 0
  335. Resume EndOfSub
  336.  
  337. EndOfSub:
  338. 'Put the mouse pointer back to normal.
  339. screen.MousePointer = 0
  340. MsgBox ("Pack Completed")
  341. Exit Sub
  342.  
  343.  
  344. End Sub
  345.  
  346.