home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Programmer'…arterly (Limited Edition) / Visual_Basic_Programmers_Journal_VB-CD_Quarterly_Limited_Edition_1995.iso / code / ch28code / generic.cls < prev    next >
Encoding:
Text File  |  1995-08-02  |  19.9 KB  |  446 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "GenericDB"
  6. Attribute VB_Creatable = True
  7. Attribute VB_Exposed = False
  8. '*********************************************************************
  9. ' GENERIC.CLS - A database class with a set of common routines.
  10. '*********************************************************************
  11. Option Explicit
  12. '*********************************************************************
  13. ' Class data members
  14. '*********************************************************************
  15. Private WSpace As Workspace     ' Class Workspace
  16. Private DBase As Database       ' Class Database
  17. Private RecSet As Recordset     ' Main Class RecordSet
  18. Private DBFileName As String    ' Filename of the database
  19. Private TBDef As TableDef       ' For creating new tables
  20. Private FieldName As Field      ' For creating new fields
  21. '*********************************************************************
  22. ' This Procedure creates the default workspace
  23. '*********************************************************************
  24. Private Sub Class_Initialize()
  25.     Set WSpace = DBEngine.Workspaces(0)
  26. End Sub
  27. '*********************************************************************
  28. ' The Recordset, Database, and Workspace are closed when the object
  29. ' goes out of scope to prevent corrupting the database.
  30. '*********************************************************************
  31. Private Sub Class_Terminate()
  32.     On Error Resume Next
  33.     RecSet.Close
  34.     DBase.Close
  35.     WSpace.Close
  36. End Sub
  37. '*********************************************************************
  38. ' Returns a reference to the workspace.
  39. '*********************************************************************
  40. Public Property Get GetWorkspace() As Workspace
  41.     Set GetWorkspace = WSpace
  42. End Property
  43. '*********************************************************************
  44. ' Returns a reference to the database.
  45. '*********************************************************************
  46. Public Property Get GetDatabase() As Database
  47.     Set GetDatabase = DBase
  48. End Property
  49. '*********************************************************************
  50. ' Returns the filename of the database that is currently open.
  51. '*********************************************************************
  52. Public Property Get FileName() As String
  53.     FileName = DBFileName
  54. End Property
  55. '*********************************************************************
  56. ' Opens a database for use with this class.
  57. '*********************************************************************
  58. Public Sub OpenDB(File$, Optional OpenExclusive, Optional OpenReadOnly)
  59. Dim res%
  60.     '*****************************************************************
  61.     ' If any arguments are missing, add default values.
  62.     '*****************************************************************
  63.     On Error Resume Next
  64.     If Not IsMissing(File) Then DBFileName = File
  65.     If IsMissing(OpenExclusive) Then OpenExclusive = False
  66.     If IsMissing(OpenReadOnly) Then OpenReadOnly = False
  67.     '*****************************************************************
  68.     ' Convert the arguments into valid booleans.
  69.     '*****************************************************************
  70.     OpenExclusive = CBool(OpenExclusive)
  71.     OpenReadOnly = CBool(OpenReadOnly)
  72.     '*****************************************************************
  73.     ' Open the database.
  74.     '*****************************************************************
  75.     Set DBase = WSpace.OpenDatabase(DBFileName, OpenExclusive, _
  76.                                                 OpenReadOnly)
  77.     '*****************************************************************
  78.     ' If the database is corrupted, then prompt to repair it.
  79.     '*****************************************************************
  80.     If Err = 3049 Then
  81.         res = MsgBox(Error & vbLf & vbLf & _
  82.                   "Would you like attempt to repair this database?", _
  83.                    vbQuestion + vbYesNo)
  84.         '*************************************************************
  85.         ' If no, then bug out.
  86.         '*************************************************************
  87.         If res = vbNo Then Exit Sub
  88.         '*************************************************************
  89.         ' Otherwise repair it, clear the error flag, and try again.
  90.         '*************************************************************
  91.         Repair DBFileName: Err = 0
  92.         Set DBase = WSpace.OpenDatabase(DBFileName, OpenExclusive, _
  93.                                         OpenReadOnly)
  94.         '*************************************************************
  95.         ' If there is another error, then give up.
  96.         '*************************************************************
  97.         If Err Then
  98.             MsgBox "An attempt to open the database failed!", vbCritical
  99.         End If
  100.     '*****************************************************************
  101.     ' If some other error, then just report it.
  102.     '*****************************************************************
  103.     ElseIf Err <> 0 And Err <> 3049 Then
  104.         MsgBox Error, vbExclamation
  105.     End If
  106. End Sub
  107. '*********************************************************************
  108. ' Creates a Recordset for use with this class.
  109. '*********************************************************************
  110. Public Sub CreateRecordSet(Source$, Optional ViewType, Optional Options)
  111.     '*****************************************************************
  112.     ' If any arguments are missing, add default values.
  113.     '*****************************************************************
  114.     If IsMissing(ViewType) Then ViewType = dbOpenDynaset
  115.     If IsMissing(Options) Then
  116.         Set RecSet = DBase.OpenRecordset(Source, CInt(ViewType))
  117.     Else
  118.         Set RecSet = DBase.OpenRecordset(Source, CInt(ViewType), _
  119.                                          CInt(Options))
  120.     End If
  121. End Sub
  122. '*********************************************************************
  123. ' Returns a reference to the currently open Recordset.
  124. '*********************************************************************
  125. Public Property Get Data() As Recordset
  126.     Set Data = RecSet
  127. End Property
  128. '*********************************************************************
  129. ' Creates a new database.
  130. '*********************************************************************
  131. Public Sub Create(File$)
  132.     If Not IsMissing(File) Then DBFileName = File
  133.     Set DBase = WSpace.CreateDatabase(DBFileName, dbLangGeneral)
  134. End Sub
  135. '*********************************************************************
  136. ' Creates a TableDef.
  137. '*********************************************************************
  138. Public Sub MakeTable(TableName As String)
  139.     Set TBDef = DBase.CreateTableDef(TableName)
  140. End Sub
  141. '*********************************************************************
  142. ' Returns a reference to the open TableDef.
  143. '*********************************************************************
  144. Public Property Get NewTable() As TableDef
  145.     Set NewTable = TBDef
  146. End Property
  147. '*********************************************************************
  148. ' Writes the TableDef to the table, so a new table can be created.
  149. '*********************************************************************
  150. Public Sub AddTable()
  151.     DBase.TableDefs.Append TBDef
  152.     Set TBDef = Nothing
  153. End Sub
  154. '*********************************************************************
  155. ' Creates a new field definintion. Other attributes should be set by
  156. ' obtaining the NewField reference, and make the changes directly.
  157. '*********************************************************************
  158. Public Sub MakeField(FName$, FType%, Optional FSize)
  159.     Set FieldName = TBDef.CreateField(FName, FType)
  160.     If Not IsMissing(FSize) Then FieldName.Size = CInt(FSize)
  161. End Sub
  162. '*********************************************************************
  163. ' Returns a reference to the currently open field definition.
  164. '*********************************************************************
  165. Public Property Get NewField() As Field
  166.     Set NewField = FieldName
  167. End Property
  168. '*********************************************************************
  169. ' Writes the field definition to the current TableDef.
  170. '*********************************************************************
  171. Public Sub AddField()
  172.     TBDef.Fields.Append FieldName
  173.     Set FieldName = Nothing
  174. End Sub
  175. '*********************************************************************
  176. ' Writes a index to a TableDef.
  177. '*********************************************************************
  178. Public Sub MakeIndex(FldName$, PrimaryKey As Boolean, UniqueKey As Boolean)
  179. Dim NewIndex As New Index      ' For creating new indexes
  180.     With NewIndex
  181.         .Name = "idx" & FldName
  182.         .Fields = FldName
  183.         .Primary = PrimaryKey
  184.         .Unique = IIf(PrimaryKey, True, UniqueKey)
  185.     End With
  186.     TBDef.Indexes.Append NewIndex
  187. End Sub
  188. '*********************************************************************
  189. ' Returns all (up to ~32k) of the records of a field in a delimited
  190. ' string. This is a useful feature for inserting data into a text box.
  191. '*********************************************************************
  192. Public Function GetData(FName$, ByVal Delimiter$) As String
  193. Dim res$, retStr$
  194.     '*****************************************************************
  195.     ' Move to the first record.
  196.     '*****************************************************************
  197.     On Error Resume Next
  198.     RecSet.MoveFirst
  199.     '*****************************************************************
  200.     ' Build a large (<=~32k) delimited string of the records.
  201.     '*****************************************************************
  202.     Do While Not RecSet.EOF
  203.         res = Trim(RecSet(FName))
  204.         If Len(res) + Len(retStr) > 32001 Then Exit Do
  205.         retStr = retStr & res & Delimiter
  206.         RecSet.MoveNext
  207.     Loop
  208.     '*****************************************************************
  209.     ' Return to the first record, and return the results.
  210.     '*****************************************************************
  211.     RecSet.MoveFirst
  212.     GetData = retStr
  213. End Function
  214. '*********************************************************************
  215. ' Same as GetData, but the data is stored in an array.
  216. '*********************************************************************
  217. Public Sub GetArrayData(FName$, retArray() As String)
  218. Dim res$, retStr$, i%
  219.     On Error Resume Next
  220.     Erase retArray
  221.     RecSet.MoveFirst
  222.     Do While Not RecSet.EOF
  223.         res = Trim(RecSet(FName))
  224.         If Len(res) + Len(retStr) > 32001 Then Exit Do
  225.         If Not IsNull(res) Then
  226.             retStr = retStr & res
  227.             ReDim Preserve retArray(i + 1)
  228.             retArray(i) = res
  229.             i = i + 1
  230.         End If
  231.         RecSet.MoveNext
  232.     Loop
  233.     RecSet.MoveFirst
  234. End Sub
  235. '*********************************************************************
  236. ' Same as GetData, but the data is loaded into a control. The control
  237. ' MUST either be a list or combo box in order for this method to work.
  238. '*********************************************************************
  239. Public Sub GetControlData(FName$, CtrlName As Control)
  240. Dim res, retStr$
  241.     On Error Resume Next
  242.     RecSet.MoveFirst
  243.     Do While Not RecSet.EOF
  244.         res = Trim(RecSet(FName))
  245.         If Len(res) + Len(retStr) > 32001 Then Exit Do
  246.         If Not IsNull(res) Then
  247.             retStr = retStr & res
  248.             CtrlName.AddItem res
  249.         End If
  250.         RecSet.MoveNext
  251.     Loop
  252.     CtrlName.ListIndex = 0
  253.     RecSet.MoveFirst
  254. End Sub
  255. '*********************************************************************
  256. ' Adds a new record, or edits an existing one. This method should not
  257. ' be used when adding or editing > 20 records (for performance reasons).
  258. '*********************************************************************
  259. Public Sub AddOrEditRecord(ByVal AddRec As Boolean, _
  260.                                            ParamArray FieldPipeValue())
  261. Dim NumItems%, i%, where%, FName$, FValue
  262.     '*****************************************************************
  263.     ' Find out how many parameters were passed. If none, then exit.
  264.     '*****************************************************************
  265.     On Error Resume Next
  266.     NumItems = UBound(FieldPipeValue)
  267.     If IsEmpty(FieldPipeValue(0)) Then Exit Sub
  268.     '*****************************************************************
  269.     ' Determine whether to add or edit the record.
  270.     '*****************************************************************
  271.     If AddRec Then
  272.         RecSet.AddNew
  273.     Else
  274.         RecSet.Edit
  275.         '*************************************************************
  276.         ' If there was no current record, then notify the user.
  277.         '*************************************************************
  278.         If Err = 3021 Then
  279.             MsgBox "Since there is no current record, it can not be edited." _
  280.                     , vbCritical
  281.             Exit Sub
  282.         End If
  283.     End If
  284.     '*****************************************************************
  285.     ' If loop through each parameter.
  286.     '*****************************************************************
  287.     For i = 0 To NumItems
  288.         '*************************************************************
  289.         ' Separate the field name from its value.
  290.         '*************************************************************
  291.         FName = FieldPipeValue(i)
  292.         where = InStr(FName, "|")
  293.         
  294.         If where = 0 And i > 1 Then
  295.             Exit For
  296.         ElseIf where = 0 And i < 1 Then
  297.             Exit Sub
  298.         End If
  299.         
  300.         FValue = Mid(FName, where + 1)
  301.         FName = CStr(Left(FName, where - 1))
  302.         '*************************************************************
  303.         ' Determine the record type, and convert the value.
  304.         '*************************************************************
  305.         Select Case RecSet(FName).Type
  306.             Case dbBoolean
  307.                 RecSet(FName) = CBool(FValue)
  308.             Case dbByte, dbInteger
  309.                 RecSet(FName) = CInt(FValue)
  310.             Case dbLong
  311.                 RecSet(FName) = CLng(FValue)
  312.             Case dbCurrency
  313.                 RecSet(FName) = CCur(FValue)
  314.             Case dbSingle
  315.                 RecSet(FName) = CSng(FValue)
  316.             Case dbDouble
  317.                 RecSet(FName) = CDbl(FValue)
  318.             '*********************************************************
  319.             ' Otherwise it must be a dbDate, dbText, dbLongBinary, &
  320.             ' dbMemo.
  321.             '*********************************************************
  322.             Case Else
  323.                 where = RecSet(FName).Size
  324.                 '*****************************************************
  325.                 ' If the record is too long, then clip it.
  326.                 '*****************************************************
  327.                 If where And (Len(FValue) > where) Then
  328.                     FValue = Left(FValue, where)
  329.                 ElseIf Len(FValue) > 32000 Then
  330.                     FValue = Left(FValue, 32000)
  331.                 End If
  332.                 RecSet(FName) = FValue
  333.         End Select
  334.     Next i
  335.     '*****************************************************************
  336.     ' Complete the transaction.
  337.     '*****************************************************************
  338.     RecSet.Update
  339. End Sub
  340. '*********************************************************************
  341. ' Move to the first record.
  342. '*********************************************************************
  343. Public Function MFirst(Optional FName) As String
  344.     On Error Resume Next
  345.     If RecSet.Type = 2 Then Exit Function
  346.     RecSet.MoveFirst
  347.     If Not IsMissing(FName) Then
  348.         MFirst = Trim(RecSet(CStr(FName)))
  349.     End If
  350. End Function
  351. '*********************************************************************
  352. ' Move to the last record.
  353. '*********************************************************************
  354. Public Function MLast(Optional FName) As String
  355.     On Error Resume Next
  356.     RecSet.MoveLast
  357.     If Not IsMissing(FName) Then
  358.         MLast = Trim(RecSet(CStr(FName)))
  359.     End If
  360. End Function
  361. '*********************************************************************
  362. ' Move to the next record.
  363. '*********************************************************************
  364. Public Function MNext(Optional FName) As String
  365.     On Error Resume Next
  366.     RecSet.MoveNext
  367.     If RecSet.EOF Then RecSet.MoveLast
  368.     If Not IsMissing(FName) Then
  369.         MNext = Trim(RecSet(CStr(FName)))
  370.     End If
  371. End Function
  372. '*********************************************************************
  373. ' Move to the previous record.
  374. '*********************************************************************
  375. Public Function MPrev(Optional FName) As String
  376.     On Error Resume Next
  377.     If RecSet.Type = 2 Then Exit Function
  378.     RecSet.MovePrevious
  379.     If RecSet.BOF Then RecSet.MoveFirst
  380.     If Not IsMissing(FName) Then
  381.         MPrev = Trim(RecSet(CStr(FName)))
  382.     End If
  383. End Function
  384. '*********************************************************************
  385. ' Locates a record, and returns its result.
  386. '*********************************************************************
  387. Public Function FindRecord(FName$, FindWhat, Optional ByVal _
  388.                            ExactMatch) As Variant
  389.     '*****************************************************************
  390.     ' Determine wheter to find a similar or exact match.
  391.     '*****************************************************************
  392.     On Error Resume Next
  393.     ExactMatch = IIf(IsMissing(ExactMatch), True, ExactMatch)
  394.     '*****************************************************************
  395.     ' Start at the beginning, and find the record.
  396.     '*****************************************************************
  397.     RecSet.MoveFirst
  398.     If ExactMatch Then
  399.         RecSet.FindFirst FName & " = '" & FindWhat & "'"
  400.     Else
  401.         RecSet.FindFirst "[" & FName & "] LIKE '" & FindWhat & "'"
  402.     End If
  403.     '*****************************************************************
  404.     ' If no match, then return "".
  405.     '*****************************************************************
  406.     FindRecord = IIf(RecSet.NoMatch, "", FindRecord = RecSet(FName))
  407. End Function
  408. '*********************************************************************
  409. ' Returns a record from a specific field.
  410. '*********************************************************************
  411. Public Function GetRecord(FName$) As Variant
  412.     On Error Resume Next
  413.     GetRecord = RecSet(FName)
  414. End Function
  415. '*********************************************************************
  416. ' Repairs and Compacts a damaged database.
  417. '*********************************************************************
  418. Public Sub Repair(FileName$)
  419. Dim BakFileName$, res%
  420.     '*****************************************************************
  421.     ' Make a copy of the database to work on.
  422.     '*****************************************************************
  423.     On Error Resume Next
  424.     BakFileName = Left(FileName, InStr(FileName, ".")) & "BAK"
  425.     FileCopy FileName, BakFileName
  426.     DBEngine.RepairDatabase BakFileName
  427.     '*****************************************************************
  428.     ' If it was successfully repaired, then kill the orginal.
  429.     '*****************************************************************
  430.     If Err = 0 Then
  431.         Kill FileName
  432.         '*************************************************************
  433.         ' Repaired databases should be compacted, so do it now.
  434.         '*************************************************************
  435.         DBEngine.CompactDatabase BakFileName, FileName
  436.         '*************************************************************
  437.         ' If it succeeded, then ask the user if they want to delete
  438.         ' the backup copy.
  439.         '*************************************************************
  440.         If Err = 0 Then
  441.             If MsgBox("Would you like to delete the backup file?", _
  442.                  vbYesNo + vbQuestion) = vbYes Then Kill BakFileName
  443.         End If
  444.     End If
  445. End Sub
  446.