home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Power Pack / Visual_Basic4_Power_Pack.bin / vb4files / vbof / vbofcoll.cls < prev    next >
Encoding:
Text File  |  1996-11-20  |  125.6 KB  |  4,001 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "VBOFCollection"
  6. Attribute VB_Creatable = True
  7. Attribute VB_Exposed = True
  8. Option Explicit
  9.  
  10. ' (c) Copyright 1995 Ken Fitzpatrick
  11. '     All Rights Reserved
  12. '     Cannot be distributed or sold without permission
  13. '
  14. ' VBObjectFrameworkCollection is a database-aware
  15. '     Collection class supplemental for Microsoft
  16. '     Visual Basic 4.0.
  17. ' This version of VBOFCollection is intended only
  18. '     to be used in conjunction with the following
  19. '     Class Modules:
  20. '       VBOFObjectManager (required)
  21. '       VBOFEventManager  (optional, see comments in VBOFObjectManager for details)
  22. '       VBOFEventObject   (optional, see comments in VBOFObjectManager for details)
  23. ' and cannot be used in a "stand-alone" mode, that
  24. '   is, without the support of the above required
  25. '   Class Modules nor can this version be used as
  26. '   the application program's initial point of
  27. '   contact with the VBObjectFramework (the required
  28. '   initial point of contace must be the
  29. '   VBOFObjectManager)
  30. '
  31.  
  32. Public ObjectID As Long
  33.  
  34. Private pvtCollection As Collection
  35.  
  36. Private pvtVBOFObjectManager As VBOFObjectManager
  37. Private pvtVBOFListBoxWrapper As VBOFListBoxWrapper
  38.  
  39. Private pvtSample As Object
  40. Private pvtParent As Object
  41. Private pvtMostRecentlyAddedObject As Object
  42. Private pvtSampleTableName As String
  43. Private pvtSampleType As String
  44. Private pvtParentTableName As String
  45. Private pvtParentType As String
  46. Private pvtListBox As Variant
  47. Private pvtDBGrid As Variant
  48. Private pvtNewIndex As Long
  49.  
  50. Private pvtDatabase As Database
  51. Private pvtRecordSet As RecordSet
  52. Private pvtSQLStatement As String
  53. Private pvtWhereClause As String
  54. Private pvtOrderByClause As String
  55. Private pvtCollectionEmulationMode As Boolean
  56. Private pvtRecordSetProvidedByUser As Boolean
  57. Private pvtSQLStatementProvidedByUser As Boolean
  58. Private pvtDBHasBeenReferenced As Boolean
  59. Private pvtANSISQL As Boolean
  60. Private pvtODBCPassThrough As Long
  61. Private pvtDBGridBookmarkArray() As Variant
  62. Private pvtDBGridBookmarkArrayAvailable As Boolean
  63. Private pvtAutoDeleteOrphans As Boolean
  64. Private pvtAutoDeleteOrphansHasBeenInitialized As Boolean
  65. Private RC As Long
  66.  
  67. Private Const pvtReceiverDoesNotSupportThisMethod = 438
  68.  
  69. Public Property Let AutoDeleteOrphans(aBoolean As Boolean)
  70.     pvtAutoDeleteOrphans = aBoolean
  71.     pvtAutoDeleteOrphansHasBeenInitialized = True
  72. End Property
  73.  
  74. Public Property Get AutoDeleteOrphans() As Boolean
  75.     If pvtAutoDeleteOrphansHasBeenInitialized Then
  76.         AutoDeleteOrphans = _
  77.             pvtAutoDeleteOrphans
  78.     Else
  79.         AutoDeleteOrphans = _
  80.             pvtVBOFObjectManager.AutoDeleteOrphans
  81.     End If
  82. End Property
  83.  
  84.  
  85. Public Function pvtEmptyCollection(Optional NoDelete As Variant, Optional CleanUpMode As Variant) As Boolean
  86. ' Empties this the VBOFCollection of all its Objects.
  87. '
  88. ' Note: if a DataSource is supporting the Collection
  89. '   then the VBOF automatic containment links to
  90. '   the contained objects are also severed
  91.  
  92.     On Local Error Resume Next
  93.     
  94.     pvtEmptyCollection = _
  95.         ObjectManager. _
  96.             EmptyCollection( _
  97.                 Collection:=Me, _
  98.                 NoDelete:=NoDelete, _
  99.                 CleanUpMode:=CleanUpMode)
  100.  
  101. End Function
  102.  
  103. Public Function pvtCloseRecordSet() As Long
  104. ' Closes the current RecordSet.  This might be
  105. '   useful if using the VBOFCollection to
  106. '   populate a ListBox or Grid.
  107. ' Returns the VB Err code associated with closing
  108. '   the RecordSet.
  109. ' Note: this method should be used with caution.
  110.  
  111.     On Local Error Resume Next
  112.  
  113.     pvtRecordSet.Close
  114.     
  115.     pvtCloseRecordSet = Err
  116. End Function
  117.  
  118.  
  119. Public Function PopulateCollection(Optional Database As Variant, Optional RecordSet As Variant, Optional Sample As Variant, Optional Parent As Variant, Optional WhereClause As Variant, Optional SQL As Variant, Optional OrderByClause As Variant, Optional ODBCPassThrough As Variant, Optional ANSISQL As Variant) As VBOFCollection
  120. Attribute PopulateCollection.VB_Description = "Populates the VBOFCollection either from the Database, or from a user-provided ResordSet"
  121. ' Returns a populated VBOFCollection.
  122. '   Serves a purpose of simplification for the
  123. '   user.  This method gives the user a single
  124. '   method to invoke for instantiating the
  125. '   VBOFCollection, regardless of whether
  126. '   the "pvtPopulateFromDatabase" method or
  127. '   the "pvtPopulateFromRecordSet" method is
  128. '   actually used.
  129. '
  130. ' Either Database:= or RecordSet:= must be provided.
  131. '   For RecordSet:= support, the caller must have
  132. '       independently created the RecordSet object.
  133. '   Otherwise, the Database:= parameter should be
  134. '       specified and VBOFCollection will create
  135. '       the underlying RecordSet automatically
  136. '
  137. ' Parameter Description:
  138. '   see VBOFObjectManager.ManageCollection
  139.  
  140. ' bullet-proofing
  141. '    If IsMissing(Database) _
  142. '    And IsMissing(RecordSet) Then
  143.     If IsMissing(RecordSet) _
  144.     And pvtDatabase Is Nothing Then
  145.         pvtErrorMessage TypeName(Me) & " cannot process the '.PopulateCollection' method because both the 'Database:=' and 'RecordSet:=' parameter are missing."
  146.         Set PopulateCollection = Me
  147.         Exit Function
  148.     End If
  149.  
  150.     If Not IsMissing(RecordSet) Then
  151.         Set PopulateCollection = _
  152.             pvtPopulateFromRecordSet( _
  153.                 RecordSet:=RecordSet, _
  154.                 Parent:=Parent, _
  155.                 Sample:=Sample, _
  156.                 SQL:=SQL, _
  157.                 ANSISQL:=ANSISQL, _
  158.                 WhereClause:=WhereClause, _
  159.                 OrderByClause:=OrderByClause, _
  160.                 ODBCPassThrough:=ODBCPassThrough)
  161.     Else
  162.         Set PopulateCollection = _
  163.             pvtPopulateFromDatabase( _
  164.                 Database:=Database, _
  165.                 Parent:=Parent, _
  166.                 Sample:=Sample, _
  167.                 SQL:=SQL, _
  168.                 ANSISQL:=ANSISQL, _
  169.                 WhereClause:=WhereClause, _
  170.                 OrderByClause:=OrderByClause, _
  171.                 ODBCPassThrough:=ODBCPassThrough)
  172.     End If
  173.  
  174. End Function
  175.  
  176. Public Function pvtDataValidate(Optional DataControl As Variant, Optional Action As Variant, Optional Save As Variant, Optional Sample As Variant, Optional Parent As Variant) As Variant
  177.  
  178.     Dim tempObject As Object
  179.     
  180.     On Local Error Resume Next
  181.  
  182. ' bullet-proofing
  183.     If IsMissing(Action) Then
  184.         Set pvtDataValidate = Nothing
  185.         Exit Function
  186.     End If
  187.     If IsMissing(Save) Then
  188.         Set pvtDataValidate = Nothing
  189.         Exit Function
  190.     End If
  191.         
  192.     If Not pvtSetSample( _
  193.             Sample:=Sample, _
  194.             MethodName:="pvtDataValidate") Then
  195.         Set pvtDataValidate = Nothing
  196.         GoTo pvtDataValidate_Exit
  197.     End If
  198.     If Not pvtSetParent( _
  199.             Parent:=Parent, _
  200.             MethodName:="pvtDataValidate") Then
  201.         Set pvtDataValidate = Nothing
  202.         Exit Function
  203.     End If
  204.  
  205. ' process according to Action
  206.     Select Case Action
  207.  
  208. ' process Action=AddNew
  209.         Case vbDataActionAddNew
  210.             
  211. ' instantiate a new object
  212.             Set tempObject = _
  213.                 ObjectManager. _
  214.                     pvtInstantiateNewObjectFromSample _
  215.                         (Sample:=pvtSample)
  216.             If tempObject Is Nothing Then
  217.                 Set pvtDataValidate = Nothing
  218.                 Exit Function
  219.             End If
  220.  
  221. ' have the new instantiated object copy populate
  222. '   itself from this RecordSet row
  223.             Set tempObject = _
  224.                 ObjectManager. _
  225.                     pvtObjectInitializeFromRecordSet( _
  226.                         Object:=tempObject, _
  227.                         RecordSet:=pvtRecordSet)
  228.             If tempObject Is Nothing Then
  229.                 Set pvtDataValidate = Nothing
  230.                 Exit Function
  231.             End If
  232.             
  233. ' add the new object to Me.RecordSet
  234.             Set tempObject = _
  235.                 Me.Add( _
  236.                     Item:=tempObject)
  237.                     
  238.             Set DataControl.RecordSet = _
  239.                 pvtRecordSet
  240.  
  241. ' process Action=Update
  242.         Case vbDataActionUpdate
  243.             
  244. ' get the object at the RecordSet row
  245.             Set tempObject = _
  246.                 pvtRecordSetMoveToRecordNumber _
  247.                     (pvtRecordSet.AbsolutePosition)
  248.  
  249. ' have the new instantiated object copy populate
  250. '   itself from this RecordSet row
  251.             Set tempObject = _
  252.                 ObjectManager. _
  253.                     pvtObjectInitializeFromRecordSet( _
  254.                         Object:=tempObject, _
  255.                         RecordSet:=pvtRecordSet)
  256.             If tempObject Is Nothing Then
  257.                 Set pvtDataValidate = Nothing
  258.                 Exit Function
  259.             End If
  260.         
  261. ' update the object in the Collection
  262.             Replace _
  263.                Item:=tempObject, _
  264.                ReplaceWith:=tempObject
  265.  
  266. ' process Action=Delete
  267.         Case vbDataActionDelete
  268.             
  269. ' get the object at the RecordSet row
  270.             Set tempObject = _
  271.                 pvtRecordSetMoveToRecordNumber _
  272.                     (pvtRecordSet.AbsolutePosition)
  273.  
  274. ' remove the object from the Collection
  275.             Remove _
  276.                 Item:=tempObject, _
  277.                 NoDelete:=True
  278.         
  279.         End Select
  280.  
  281. pvtDataValidate_Exit:
  282.     Set pvtDataValidate = tempObject
  283.     Set tempObject = Nothing
  284. End Function
  285.  
  286.  
  287. Private Function pvtIsAnOrphan(Optional Item As Variant) As Boolean
  288. ' Determines whether or not the Item is an Orphan
  289.  
  290.     Dim tempCountOfParentLinksToItem As Long
  291.  
  292. ' count the number of Parent objects which currently
  293. '   reference Item
  294.     tempCountOfParentLinksToItem = _
  295.         pvtCountOfParentLinksToItem( _
  296.            Child:=Item, _
  297.            Parent:=pvtParent)
  298.  
  299.     If tempCountOfParentLinksToItem > 0 Then
  300.         pvtIsAnOrphan = False
  301.     Else
  302.         pvtIsAnOrphan = True
  303.     End If
  304. End Function
  305.  
  306.  
  307. Public Function ObjectDataSource() As String
  308. Attribute ObjectDataSource.VB_Description = "Private"
  309.     ObjectDataSource = "VBObjectFrameworkObjectLinks"
  310. End Function
  311.  
  312. Private Function pvtAddUniqueItemToCollection(Optional Item As Variant, Optional Parent As Variant, Optional Collection As Variant) As Variant
  313. ' Add the Item to the Collection, if it is unique.
  314. ' Return the object which is actually added to
  315. '   the Collection
  316.         
  317.     Dim tempObject As Object
  318.         
  319.     On Local Error Resume Next
  320.     
  321. ' bullet-proofing
  322.     If IsMissing(Item) _
  323.     Or IsMissing(Parent) _
  324.     Or IsMissing(Collection) Then
  325.         Set pvtAddUniqueItemToCollection = Nothing
  326.         Exit Function
  327.     End If
  328.         
  329. ' verify that the object is unique across
  330. '   the known system objects
  331.     Set tempObject = _
  332.         pvtVBOFObjectManager. _
  333.             AddUniqueObject( _
  334.                 Object:=Item, _
  335.                 Parent:=Parent)
  336.  
  337. ' add the object to the collection
  338.     Collection.Add _
  339.         Item:=tempObject, _
  340.         Key:=CStr(tempObject.ObjectID)
  341.  
  342. ' add the reference to the pvtDBGridBookmarkArray
  343.     pvtAddItemToDBGridArray _
  344.         Item:=tempObject, _
  345.         Collection:=Collection
  346.  
  347. ' return the unique object
  348.     Set pvtAddUniqueItemToCollection = _
  349.         tempObject
  350. End Function
  351.  
  352. Private Function pvtCollectionIndexForWhereClause(Optional WhereClause As Variant, Optional FindFirst As Variant, Optional FindNext As Variant, Optional FindLast As Variant, Optional FindPrevious As Variant) As Variant
  353. ' Returns the next object in the collection which
  354. '   meets the criteria of the WhereClause.
  355. ' Note: processing is based on the RecordSet, thus
  356. '   positioning is relative to the positioning of
  357. '   the underlying RecordSet.  See also methods
  358. '   "RecordSet" and "pvtRecordSetMoveFirst"
  359. ' Parameters:
  360. '   WhereClause - a search string which can be
  361. '       appended to the RecordSet.FindNext method
  362. '   FindFirst - a boolean which determines whether
  363. '       the FindNext or FindFirst method should be
  364. '       used
  365.  
  366.     Dim tempFindFirst As Boolean
  367.     Dim tempFindNext As Boolean
  368.     Dim tempFindLast As Boolean
  369.     Dim tempFindPrevious As Boolean
  370.     Dim tempObjectID As Long
  371.     Dim I As Long
  372.     Dim tempObject As Variant
  373.  
  374.     On Local Error Resume Next
  375.     
  376.     tempFindNext = True
  377.  
  378. ' bullet-proofing
  379.     If pvtRecordSet Is Nothing Then
  380.         pvtCollectionIndexForWhereClause = -1
  381.         GoTo pvtCollectionIndexForWhereClause_Exit
  382.     End If
  383.     If pvtCollection.Count <= 0 Then
  384.         pvtCollectionIndexForWhereClause = -1
  385.         GoTo pvtCollectionIndexForWhereClause_Exit
  386.     End If
  387.     If pvtCollection(1).ObjectDataSource = "" Or Err = 438 Then
  388.         pvtCollectionIndexForWhereClause = -1
  389.         GoTo pvtCollectionIndexForWhereClause_Exit
  390.     End If
  391.     
  392. ' set FindFirst
  393.     tempFindFirst = False
  394.     If Not IsMissing(FindFirst) Then
  395.         tempFindFirst = FindFirst
  396.     End If
  397.     
  398. ' set FindLast
  399.     tempFindLast = False
  400.     If Not IsMissing(FindLast) Then
  401.         tempFindLast = FindLast
  402.     End If
  403.     
  404. ' set FindPrevious
  405.     tempFindPrevious = False
  406.     If Not IsMissing(FindPrevious) Then
  407.         tempFindPrevious = FindPrevious
  408.     End If
  409.     
  410. ' search for the next qualifying row in the RecordSet
  411.     If tempFindPrevious Then
  412.         pvtRecordSet.FindPrevious WhereClause
  413.     ElseIf tempFindLast Then
  414.         pvtRecordSet.FindLast WhereClause
  415.     ElseIf tempFindFirst Then
  416.         pvtRecordSet.FindFirst WhereClause
  417.     Else
  418.         pvtRecordSet.FindNext WhereClause
  419.     End If
  420.     
  421.     If pvtRecordSet.NoMatch Then
  422.         pvtCollectionIndexForWhereClause = -1
  423.         GoTo pvtCollectionIndexForWhereClause_Exit
  424.     End If
  425.  
  426. ' save the ObjectID of the found record
  427.     tempObjectID = pvtRecordSet("ObjectID")
  428.  
  429. ' search for the corresponding object
  430.     I = 1
  431.     For Each tempObject In pvtCollection
  432.         If tempObject.ObjectID = tempObjectID Then
  433.             pvtCollectionIndexForWhereClause = I
  434.             GoTo pvtCollectionIndexForWhereClause_Exit
  435.         End If
  436.         
  437.         I = I + 1
  438.     Next tempObject
  439.  
  440.     pvtCollectionIndexForWhereClause = -1
  441.  
  442. pvtCollectionIndexForWhereClause_Exit:
  443.     Set tempObject = Nothing
  444.     
  445. End Function
  446.  
  447.  
  448. Public Function pvtDBGridUnboundReadData(Optional DBGrid As Variant, Optional RowBuf As Variant, Optional StartLocation As Variant, Optional ReadPriorRows As Variant) As Long
  449. ' Populates the DBGrid with one row of information
  450. '   for each object in this VBOFCollection.
  451. ' Returns the number of rows added to the DBGrid
  452. ' Note:  the referenced objects must contain the
  453. '   method 'ObjectDBGridValue', which must populate
  454. '   and return the RowBuffer object
  455. '   (for more information, find "RowBuffer" in the
  456. '   online VB Help.)
  457. '
  458. ' Note:  this method should be coded in the
  459. '   DBGrid's UnboundReadData Event Procedure,
  460. '   as follows:
  461. '
  462. '   Private Sub DBGrid1_UnboundReadData(ByVal RowBuf As RowBuffer, StartLocation As Variant, ByVal ReadPriorRows As Boolean)
  463. '       MyVBOFCollection.pvtDBGridUnboundReadData _
  464. '           DBGrid:=DBGrid1, _
  465. '           RowBuf:=RowBuf, _
  466. '           StartLocation:=StartLocation, _
  467. '           ReadPriorRows:=ReadPriorRows
  468. '   End Sub
  469.  
  470.     Dim tempObject As Object
  471.     Dim tempIncrement As Long
  472.     Dim tempCurrentRowIndex As Long
  473.     Dim tempRowIndex As Long
  474.     Dim tempColumnIndex As Long
  475.     Dim tempRowsFetched As Long
  476.     Dim tempBookmark As Variant
  477.     
  478.     On Local Error Resume Next
  479.     
  480. ' bullet-proofing
  481.     If IsMissing(DBGrid) Or IsMissing(RowBuf) Then
  482.         If pvtDBGrid Is Nothing Then
  483.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridUnboundReadData' method for this object because the 'DBGrid' or 'RowBuf' parameter is missing."
  484.             pvtDBGridUnboundReadData = False
  485.             GoTo pvtDBGridUnboundReadData_Exit
  486.         End If
  487.     Else
  488.         Set pvtDBGrid = DBGrid
  489.     End If
  490.     
  491.     If ReadPriorRows Then
  492.         tempIncrement = -1
  493.     Else
  494.         tempIncrement = 1
  495.     End If
  496.  
  497.     tempBookmark = StartLocation
  498.  
  499. ' process the row
  500.     tempRowsFetched = 0
  501.     For tempRowIndex = 0 To RowBuf.RowCount - 1
  502.         
  503.         tempBookmark = _
  504.             pvtDBGridGetRelativeBookmark( _
  505.                 tempBookmark, _
  506.                 tempIncrement, _
  507.                 pvtCollection.Count)
  508.  
  509.         If IsNull(tempBookmark) Then
  510.             Exit For
  511.         End If
  512.  
  513. ' reference the object associated with the
  514. '   current row, indexed by relative position
  515. '   within the pvtCollection
  516.         Set tempObject = _
  517.             pvtCollection.Item _
  518.                 (CLng(tempBookmark) + 1)
  519.  
  520. ' have the object complete the RowBuf
  521. '   with its own Property values
  522.         tempObject.ObjectDBGridUnboundReadData _
  523.             DBGrid:=pvtDBGrid, _
  524.             RowBuf:=RowBuf, _
  525.             RowNumber:=tempCurrentRowIndex
  526.  
  527. ' assign the Bookmark to the row, as returned above.
  528. '   Internally, the CollectionIndex(Object) is used
  529.         RowBuf.Bookmark(tempRowIndex) = _
  530.             tempBookmark
  531.             
  532.         tempCurrentRowIndex = tempCurrentRowIndex + tempIncrement
  533.         tempRowsFetched = tempRowsFetched + 1
  534.         
  535.     Next tempRowIndex
  536.  
  537. pvtDBGridUnboundReadData_Exit:
  538.     Set tempObject = Nothing
  539.     RowBuf.RowCount = tempRowsFetched
  540.     pvtDBGridUnboundReadData = tempRowsFetched
  541. End Function
  542.  
  543. Public Function pvtDBGridUnboundAddData(Optional DBGrid As Variant, Optional RowBuf As Variant, Optional NewRowBookmark As Variant, Optional Sample As Variant, Optional Parent As Variant) As Variant
  544. ' Processes the UnboundAddData event of the DBGrid.
  545. '   Automatically instantiates a new object,
  546. '   populates it, adds it to the VBOFCollection
  547. '   and returns the VBOFCollection to the
  548. '   application.
  549. '
  550. ' Parameters:
  551. '   DBGrid:= identifies the DBGrid
  552. '   RowBuf:= is the same RowBuf parameter found
  553. '       in the application's UnboundAddData event
  554. '       handler
  555. '   NewRowBookmark:= is the same NewRowBookmark
  556. '       parameter found in the application's
  557. '       UnboundAddData event handler
  558. '   Sample:= (Optional) identifies the class
  559. '       type to instantiate with the new data.
  560. '       If a previous VBOFCollection method had
  561. '       already established a Sample:=, this
  562. '       parameter can be eliminated
  563. '   Parent:= (Optional) identifies the object
  564. '       which is the parent ("container") object of
  565. '       the objects in this collection.
  566. '       If a previous VBOFCollection method had
  567. '       already established a Parent:=, this
  568. '       parameter can be eliminated
  569. '
  570. ' Note:  this method should be coded as follows:
  571. '   Private Sub DBGrid1_UnboundAddData(ByVal RowBuf As RowBuffer, NewRowBookmark As Variant)
  572. '       MyVBOFCollection.pvtDBGridUnboundAddData _
  573. '           DBGrid:=DBGrid1, _
  574. '           RowBuf:=RowBuf, _
  575. '           NewRowBookmark:=NewRowBookmark
  576. '
  577. ' or,
  578. '       Dim tempSample as New MyClass
  579. '       MyVBOFCollection.pvtDBGridUnboundAddData _
  580. '           DBGrid:=DBGrid1, _
  581. '           RowBuf:=RowBuf, _
  582. '           NewRowBookmark:=NewRowBookmark, _
  583. '           Sample:=tempSample
  584. '   End Sub
  585.  
  586.     Dim tempNewObject As Object
  587.     
  588.     On Local Error Resume Next
  589.     
  590. ' bullet-proofing
  591.     If IsMissing(DBGrid) _
  592.     Or IsMissing(RowBuf) _
  593.     Or IsMissing(NewRowBookmark) Then
  594.         If pvtDBGrid Is Nothing Then
  595.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridUnboundAddData' method for this object because the 'DBGrid', 'RowBuf' or 'NewRowBookmark' parameter is missing."
  596.             Set pvtDBGridUnboundAddData = Nothing
  597.             GoTo pvtDBGridUnboundAddData_Exit
  598.         End If
  599.     Else
  600.         Set pvtDBGrid = DBGrid
  601.     End If
  602.     If Not pvtSetSample( _
  603.             Sample:=Sample, _
  604.             MethodName:="pvtDBGridUnboundAddData") Then
  605.         Set pvtDBGridUnboundAddData = Nothing
  606.         GoTo pvtDBGridUnboundAddData_Exit
  607.     End If
  608.     If Not pvtSetParent( _
  609.             Parent:=Parent, _
  610.             MethodName:="pvtDBGridUnboundAddData") Then
  611.         Set pvtDBGridUnboundAddData = Nothing
  612.         GoTo pvtDBGridUnboundAddData_Exit
  613.     End If
  614.  
  615. ' instantiate the new object
  616.     Set tempNewObject = _
  617.         ObjectManager. _
  618.             pvtInstantiateNewObjectFromSample _
  619.                 (Sample:=pvtSample)
  620.     If tempNewObject Is Nothing Then
  621.         GoTo pvtDBGridUnboundAddData_Exit
  622.     End If
  623.  
  624. ' have the object populate the object from
  625. '   the new row
  626.     If tempNewObject. _
  627.         ObjectDBGridUnboundAddData( _
  628.             DBGrid:=pvtDBGrid, _
  629.             RowBuf:=RowBuf, _
  630.             NewRowBookmark:=NewRowBookmark) Then
  631.         
  632. ' add the object to the collection and Database,
  633. '   if applicable
  634.         Add _
  635.             Item:=tempNewObject, _
  636.             After:=pvtCollection.Count
  637.     End If
  638.  
  639. pvtDBGridUnboundAddData_Exit:
  640.     Set tempNewObject = Nothing
  641.     Set pvtDBGridUnboundAddData = Me
  642. End Function
  643.  
  644. Public Function pvtDBGridUnboundWriteData(Optional DBGrid As Variant, Optional RowBuf As Variant, Optional WriteLocation As Variant) As Variant
  645. ' Processes the UnboundWriteData event of the DBGrid.
  646. '
  647. ' Parameters:
  648. '   DBGrid:= identifies the DBGrid
  649. '   RowBuf:= is the same RowBuf parameter found
  650. '       in the application's UnboundWriteData event
  651. '       handler
  652. '   WriteLocation:= is the same WriteLocation
  653. '       parameter found in the application's
  654. '       UnboundWriteData event handler
  655. '
  656. ' Note:  this method should be coded as follows:
  657. '   Private Sub DBGrid1_UnboundWriteData(Optional RowBuf As Variant, Optional WriteLocation As Variant)
  658. '       MyVBOFCollection.pvtDBGridUnboundWriteData _
  659. '           DBGrid:=DBGrid1, _
  660. '           RowBuf:=RowBuf, _
  661. '           WriteLocation:=WriteLocation
  662. '   End Sub
  663.  
  664.     Dim tempObjectID As Long
  665.     Dim tempObject As Object
  666.     
  667.     On Local Error Resume Next
  668.     
  669. ' bullet-proofing
  670.     If IsMissing(RowBuf) Then
  671.         pvtErrorMessage TypeName(Me) & " cannot process the '.UnboundWriteData' method for this object because the 'RowBuf:=' parameter is missing."
  672.         Set pvtDBGridUnboundWriteData = Nothing
  673.         GoTo pvtDBGridUnboundWriteData_Exit
  674.     End If
  675.     If IsMissing(WriteLocation) Then
  676.         pvtErrorMessage TypeName(Me) & " cannot process the '.UnboundWriteData' method for this object because the 'WriteLocation:=' parameter is missing."
  677.         Set pvtDBGridUnboundWriteData = Nothing
  678.         GoTo pvtDBGridUnboundWriteData_Exit
  679.     End If
  680.     If IsMissing(DBGrid) Then
  681.         If pvtDBGrid Is Nothing Then
  682.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridUnboundAddData' method for this object because the 'DBGrid' parameter is missing."
  683.             Set pvtDBGridUnboundWriteData = Nothing
  684.             GoTo pvtDBGridUnboundWriteData_Exit
  685.         End If
  686.     Else
  687.         Set pvtDBGrid = DBGrid
  688.     End If
  689.  
  690. ' position to the correct object
  691.     Set tempObject = _
  692.         pvtCollection.Item _
  693.             (CollectionIndex _
  694.                 (Key:=pvtDBGridObjectIDAtBookmark _
  695.                     (WriteLocation)))
  696.  
  697.     If tempObject Is Nothing Then
  698.         Set pvtDBGridUnboundWriteData = Nothing
  699.         GoTo pvtDBGridUnboundWriteData_Exit
  700.     End If
  701.  
  702. ' have the object populate the object from
  703. '   the DBGrid row
  704.     tempObject. _
  705.         ObjectDBGridUnboundAddData _
  706.             DBGrid:=pvtDBGrid, _
  707.             RowBuf:=RowBuf, _
  708.             NewRowBookmark:=WriteLocation
  709.     If Err = pvtReceiverDoesNotSupportThisMethod Then
  710.         pvtErrorMessage "Class Module '" & TypeName(tempObject) & "' does not support the method 'ObjectDBGridUnboundAddData'." & vbCrLf & "Object cannot be supported by " & TypeName(Me) & " without this method."
  711.         GoTo pvtDBGridUnboundWriteData_Exit
  712.     End If
  713.         
  714. ' update the object in the Collection
  715.      Replace _
  716.         Item:=tempObject, _
  717.         ReplaceWith:=tempObject
  718.  
  719. pvtDBGridUnboundWriteData_Exit:
  720.     Set tempObject = Nothing
  721.     Set pvtDBGridUnboundWriteData = Me
  722. End Function
  723.  
  724. Public Function pvtDBGridUnboundDeleteRow(Optional DBGrid As Variant, Optional Bookmark As Variant) As Variant
  725. ' Processes the UnboundDeleteRow event of the
  726. '   DBGrid.
  727. '
  728. ' Parameters:
  729. '   DBGrid:= identifies the DBGrid
  730. '   Bookmark:= is the same Bookmark parameter found
  731. '       in the application's UnboundDeleteRow event
  732. '       handler
  733. '
  734. ' Note:  this method should be coded as follows:
  735. '   Private Sub DBGrid1_UnboundDeleteRow(Optional Bookmark As Variant)
  736. '       MyVBOFCollection.UnboundDeleteRow _
  737. '           DBGrid:=DBGrid1, _
  738. '           Bookmark:=Bookmark
  739. '   End Sub
  740.  
  741.     Dim tempObjectID As Long
  742.     Dim tempObject As Object
  743.     
  744.     On Local Error Resume Next
  745.     
  746. ' bullet-proofing
  747.     If IsMissing(Bookmark) Then
  748.         pvtErrorMessage TypeName(Me) & " cannot process the '.UnboundDeleteRow' method for this object because the 'Bookmark:=' parameter is missing."
  749.         Set pvtDBGridUnboundDeleteRow = Nothing
  750.         GoTo pvtDBGridUnboundDeleteRow_Exit
  751.     End If
  752.     If IsMissing(DBGrid) Then
  753.         If pvtDBGrid Is Nothing Then
  754.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridUnboundAddData' method for this object because the 'DBGrid' parameter is missing."
  755.             Set pvtDBGridUnboundDeleteRow = Nothing
  756.             GoTo pvtDBGridUnboundDeleteRow_Exit
  757.         End If
  758.     Else
  759.         Set pvtDBGrid = DBGrid
  760.     End If
  761.  
  762. ' position to the correct object
  763.     Set tempObject = _
  764.         pvtCollection.Item _
  765.             (CollectionIndex _
  766.                 (Key:=pvtDBGridObjectIDAtBookmark _
  767.                     (Bookmark)))
  768.  
  769.     If tempObject Is Nothing Then
  770.         Set pvtDBGridUnboundDeleteRow = Nothing
  771.         GoTo pvtDBGridUnboundDeleteRow_Exit
  772.     End If
  773.  
  774. ' remove the object from the Collection
  775.     Remove _
  776.         Item:=tempObject, _
  777.         NoDelete:=True
  778.  
  779. pvtDBGridUnboundDeleteRow_Exit:
  780.     Set tempObject = Nothing
  781.     Set pvtDBGridUnboundWriteData = Me
  782. End Function
  783.  
  784. Public Function pvtDBGridSetNumberOfRows(Optional DBGrid As Variant) As Boolean
  785. ' Informs the DBGrid of the number of rows that
  786. '   are to be added
  787. ' Note:  the referenced objects must contain the
  788. '   method 'ObjectDBGridValue', which must populate
  789. '   and return the RowBuffer object
  790. '   (for more information, find "RowBuffer" in the
  791. '   online VB Help.)
  792. '
  793. ' Note:  this method should be coded as follows:
  794. '   Private Sub Form_Load()
  795. '       MyVBOFCollection.pvtDBGridSetNumberOfRows _
  796. '           DBGrid=MyDBGrid
  797. '   End Sub
  798.  
  799.     On Local Error Resume Next
  800.     
  801. ' bullet-proofing
  802.     If IsMissing(DBGrid) Then
  803.         If pvtDBGrid Is Nothing Then
  804.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridSetNumberOfRows' method for this object because the 'DBGrid' parameter is missing."
  805.             pvtDBGridSetNumberOfRows = False
  806.             Exit Function
  807.         End If
  808.     Else
  809.         Set pvtDBGrid = DBGrid
  810.     End If
  811.  
  812.     pvtDBGrid.RowBuffer.RowCount = _
  813.         pvtCollection.Count
  814.  
  815. End Function
  816.  
  817. Public Property Get pvtDBGridBookmark(DBGrid As Variant) As Variant
  818. ' Returns the Bookmark value of the DBGrid
  819. ' Using this method:
  820. '       myObjectID = _
  821. '           MyCollection.pvtDBGridBookmark _
  822. '               (DBGrid1)
  823.                 
  824.     Dim tempBookmark As Variant
  825.     
  826.     On Local Error Resume Next
  827.     
  828. ' bullet-proofing
  829.     If IsMissing(DBGrid) Then
  830.         If pvtDBGrid Is Nothing Then
  831.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridBookmark' method for this object because the 'DBGrid' parameter is missing."
  832.             pvtDBGridBookmark = -1
  833.             Exit Property
  834.         End If
  835.     Else
  836.         Set pvtDBGrid = DBGrid
  837.     End If
  838.  
  839.     tempBookmark = _
  840.         pvtDBGrid.Bookmark
  841.     
  842.     If Err = 0 Then
  843.         pvtDBGridBookmark = _
  844.             tempBookmark
  845.     Else
  846.         pvtDBGridBookmark = Null
  847.     End If
  848.  
  849. End Property
  850.  
  851. Public Property Let pvtDBGridBookmark(DBGrid As Variant, Bookmark As Variant)
  852. ' Sets the Bookmark value of the DBGrid
  853. ' Using this method:
  854. '       MyCollection.pvtDBGridBookmark _
  855. '           (DBGrid1) = MyBookMark
  856.     
  857.     On Local Error Resume Next
  858.     
  859. ' bullet-proofing
  860.     If IsMissing(DBGrid) Or IsMissing(Bookmark) Then
  861.         If pvtDBGrid Is Nothing Then
  862.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridBookmark' method for this object because the 'DBGrid' or 'Bookmark' parameter is missing."
  863.             Exit Property
  864.         End If
  865.     Else
  866.         Set pvtDBGrid = DBGrid
  867.     End If
  868.  
  869.     pvtDBGrid.Bookmark = Bookmark
  870.  
  871. End Property
  872.  
  873.  
  874. Public Property Get pvtDBGridBookmarkObject(DBGrid As Variant) As Variant
  875. ' Returns the Object at the Bookmark value of the
  876. '   DBGrid
  877. ' Using this method:
  878. '       MyObject = _
  879. '           MyCollection.pvtDBGridBookmarkObject _
  880. '               (DBGrid1)
  881.                 
  882.     Dim tempBookmark As Variant
  883.     
  884.     On Local Error Resume Next
  885.     
  886. ' bullet-proofing
  887.     If IsMissing(DBGrid) Then
  888.         If pvtDBGrid Is Nothing Then
  889.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridBookmarkObject' method for this object because the 'DBGrid' parameter is missing."
  890.             Set pvtDBGridBookmarkObject = Nothing
  891.             Exit Property
  892.         End If
  893.     Else
  894.         Set pvtDBGrid = DBGrid
  895.     End If
  896.  
  897.     tempBookmark = _
  898.         pvtDBGridBookmark(pvtDBGrid)
  899.     
  900. ' translate the Bookmark into an Item in the
  901. '   Collection
  902.     If Not IsNull(tempBookmark) Then
  903.         Set pvtDBGridBookmarkObject = ( _
  904.             pvtCollection.Item( _
  905.                 CollectionIndex( _
  906.                     Key:=pvtDBGridObjectIDAtBookmark _
  907.                         (tempBookmark))))
  908.     Else
  909.         Set pvtDBGridBookmarkObject = _
  910.             Nothing
  911.     End If
  912.  
  913. End Property
  914.  
  915. Public Property Set pvtDBGridBookmarkObject(DBGrid As Variant, Object As Variant)
  916. ' Sets the Bookmark of the DBGrid to the position
  917. '   of Object
  918. ' Using this method:
  919. '       Set MyCollection.pvtDBGridBookmarkObject _
  920. '           (DBGrid1) = MyObject
  921.                 
  922.     Dim tempLong As Long
  923.     Dim tempBookmark As Variant
  924.     Dim tempRow As Long
  925.     
  926.     On Local Error Resume Next
  927.     
  928. ' bullet-proofing
  929.     If IsMissing(DBGrid) Or IsMissing(Object) Then
  930.         If pvtDBGrid Is Nothing Then
  931.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtDBGridBookmarkObject' method for this object because the 'DBGrid' or 'Object' parameter is missing."
  932.             Exit Property
  933.         End If
  934.     Else
  935.         Set pvtDBGrid = DBGrid
  936.     End If
  937.  
  938. ' translate Object.ObjectID to a Bookmark
  939.     tempLong = Object.ObjectID
  940.     If tempLong >= 0 Then
  941.         tempRow = _
  942.             pvtDBGridRowIndexAtObjectID( _
  943.                 CStr(tempLong))
  944.                 
  945.         pvtDBGrid.Row = tempRow
  946.                 
  947.         pvtDBGrid.Bookmark = _
  948.             pvtDBGridBookmarkAtRowIndex _
  949.                 (tempRow)
  950.     End If
  951. End Property
  952.  
  953.  
  954. Public Property Get pvtListBoxListIndex(ListBox As Variant) As Long
  955. ' Returns the ListBox's ListIndex
  956. ' Note:  this method should be used as follows:
  957. '       MyListIndex = _
  958. '           MyVBOFCollection.pvtListBoxListIndex _
  959. '               (MyListBox)
  960.         
  961.     On Local Error Resume Next
  962.     
  963. ' bullet-proofing
  964.     If IsMissing(ListBox) Then
  965.         If pvtListBox Is Nothing Then
  966.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxListIndex' method for this object because the 'ListBox' or 'ListIndex' parameter is missing."
  967.             Exit Property
  968.         End If
  969.     Else
  970.         Set pvtListBox = ListBox
  971.     End If
  972.  
  973.     pvtListBoxListIndex = _
  974.         pvtListBox.ListIndex
  975.  
  976. End Property
  977.  
  978.  
  979. Public Property Let pvtListBoxListIndex(ListBox As Variant, ByVal ListIndex As Long)
  980. ' Sets the ListBox's ListIndex
  981. ' Note:  this method should be used as follows:
  982. '       MyVBOFCollection.pvtListBoxListIndex _
  983. '               (MyListBox) = MyListIndex
  984.         
  985.     On Local Error Resume Next
  986.     
  987. ' bullet-proofing
  988.     If IsMissing(ListBox) Or IsMissing(ListIndex) Then
  989.         If pvtListBox Is Nothing Then
  990.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxListIndex' method for this object because the 'ListBox' or 'ListIndex' parameter is missing."
  991.             Exit Property
  992.         End If
  993.     Else
  994.         Set pvtListBox = ListBox
  995.     End If
  996.  
  997.     If pvtListBox.ListCount > 0 _
  998.     And pvtListBox.ListCount >= ListIndex Then
  999.         pvtListBox.ListIndex = ListIndex
  1000.     Else
  1001.         pvtListBox.ListIndex = -1
  1002.     End If
  1003.     
  1004. End Property
  1005.  
  1006. Public Property Get pvtComboBoxText(ComboBox As Variant) As String
  1007. ' Returns the ComboBox's Text property
  1008. ' Note:  this method should be used as follows:
  1009. '       MyString = _
  1010. '           MyVBOFCollection.pvtComboBoxText (ComboBox1)
  1011.         
  1012.     On Local Error Resume Next
  1013.     
  1014. ' bullet-proofing
  1015.     If IsMissing(ComboBox) Then
  1016.         If pvtListBox Is Nothing Then
  1017.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtComboBoxText' method for this object because the 'ComboBox' parameter is missing."
  1018.             pvtComboBoxText = ""
  1019.             Exit Property
  1020.         End If
  1021.     Else
  1022.         Set pvtListBox = ComboBox
  1023.     End If
  1024.  
  1025.     pvtComboBoxText = pvtListBox.Text
  1026.  
  1027. End Property
  1028.  
  1029. Public Property Let pvtComboBoxText(ComboBox As Variant, Text As String)
  1030. ' Sets the ComboBox's Text property
  1031. ' Note:  this method should be used as follows:
  1032. '       MyVBOFCollection.pvtComboBoxText (ComboBox1) = _
  1033. '           MyString
  1034.         
  1035.     On Local Error Resume Next
  1036.     
  1037. ' bullet-proofing
  1038.     If IsMissing(ComboBox) Then
  1039.         If pvtListBox Is Nothing Then
  1040.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtComboBoxText' method for this object because the 'ComboBox' parameter is missing."
  1041.             Exit Property
  1042.         End If
  1043.     Else
  1044.         Set pvtListBox = ComboBox
  1045.     End If
  1046.  
  1047.     pvtListBox.Text = Text
  1048.  
  1049. End Property
  1050.  
  1051.  
  1052.  
  1053. Public Function pvtListBoxListCount(Optional ListBox As Variant) As Long
  1054. ' Returns the ListBox's ListCount property
  1055. ' Note:  this method should be used as follows:
  1056. '       MyListCount = _
  1057. '           MyVBOFCollection.pvtListBoxListCount (MyListBox)
  1058.         
  1059.     On Local Error Resume Next
  1060.     
  1061. ' bullet-proofing
  1062.     If IsMissing(ListBox) Then
  1063.         If pvtListBox Is Nothing Then
  1064.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxListCount' method for this object because the 'ListBox' parameter is missing."
  1065.             pvtListBoxListCount = -1
  1066.             Exit Function
  1067.         End If
  1068.     Else
  1069.         Set pvtListBox = ListBox
  1070.     End If
  1071.  
  1072.     pvtListBoxListCount = pvtListBox.ListCount
  1073.  
  1074. End Function
  1075.  
  1076. Public Function pvtListBoxRefresh(Optional ListBox As Variant) As Boolean
  1077. ' Refreshes the display of the ListBox
  1078. ' Note:  this method should be coded as follows:
  1079. '       MyVBOFCollection.pvtListBoxRefresh _
  1080. '          MyListBox
  1081.  
  1082.     On Local Error Resume Next
  1083.     
  1084. ' bullet-proofing
  1085.     If IsMissing(ListBox) Then
  1086.         If pvtListBox Is Nothing Then
  1087.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxRefresh' method for this object because the 'ListBox' parameter is missing."
  1088.             Set pvtListBoxRemoveItem = False
  1089.             Exit Function
  1090.         End If
  1091.     Else
  1092.         Set pvtListBox = ListBox
  1093.     End If
  1094.  
  1095. ' clear and populate the ListBox
  1096.     pvtListBoxClear ListBox
  1097.     pvtListBoxAddItems ListBox
  1098.  
  1099.     pvtListBoxRefresh = True
  1100. End Function
  1101.  
  1102. Public Property Get pvtListBoxTopIndex(ListBox As Variant) As Long
  1103. ' Returns the ListBox's TopIndex property
  1104. ' Note:  this method should be used as follows:
  1105. '       MyTopIndex = _
  1106. '           MyVBOFCollection.pvtListBoxTopIndex _
  1107. '               (MyListBox)
  1108.         
  1109.     On Local Error Resume Next
  1110.     
  1111. ' bullet-proofing
  1112.     If IsMissing(ListBox) Then
  1113.         If pvtListBox Is Nothing Then
  1114.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxTopIndex' method for this object because the 'ListBox' parameter is missing."
  1115.             pvtListBoxTopIndex = -1
  1116.             Exit Property
  1117.         End If
  1118.     Else
  1119.         Set pvtListBox = ListBox
  1120.     End If
  1121.  
  1122.     pvtListBoxTopIndex = pvtListBox.TopIndex
  1123. End Property
  1124.  
  1125. Public Property Let pvtListBoxTopIndex(ListBox As Variant, ListIndex As Long)
  1126. ' Sets the ListBox's TopIndex property to ListIndex
  1127. ' Note:  this method should be used as follows:
  1128. '     MyVBOFCollection.pvtListBoxTopIndex _
  1129. '         (MyListBox) = MyTopIndex
  1130.         
  1131.     On Local Error Resume Next
  1132.     
  1133. ' bullet-proofing
  1134.     If IsMissing(ListBox) Then
  1135.         If pvtListBox Is Nothing Then
  1136.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxTopIndex' method for this object because the 'ListBox' parameter is missing."
  1137.             Exit Property
  1138.         End If
  1139.     Else
  1140.         Set pvtListBox = ListBox
  1141.     End If
  1142.     If IsMissing(ListIndex) Then
  1143.         pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxTopIndex' method for this object because the 'ListIndex' parameter is missing."
  1144.         Exit Property
  1145.     End If
  1146.  
  1147.     pvtListBox.TopIndex = ListIndex
  1148. End Property
  1149.  
  1150.  
  1151. Public Property Get pvtListBoxTopObject(ListBox As Variant) As Variant
  1152. ' Returns the Object at the ListBox's TopIndex property
  1153. ' Note:  this method should be used as follows:
  1154. '       Set MyTopObject = _
  1155. '           MyVBOFCollection.pvtListBoxTopObject (MyListBox)
  1156.         
  1157.     On Local Error Resume Next
  1158.     
  1159. ' bullet-proofing
  1160.     If IsMissing(ListBox) Then
  1161.         If pvtListBox Is Nothing Then
  1162.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxTopIndex' method for this object because the 'ListBox' parameter is missing."
  1163.             Set pvtListBoxTopObject = Nothing
  1164.             Exit Property
  1165.         End If
  1166.     Else
  1167.         Set pvtListBox = ListBox
  1168.     End If
  1169.  
  1170.     Set pvtListBoxTopObject = _
  1171.         pvtCollection.Item(pvtListBox.TopIndex + 1)
  1172. End Property
  1173.  
  1174. Public Property Set pvtListBoxTopObject(ListBox As Variant, Object As Variant)
  1175. ' Sets the ListBox's TopIndex property to be the
  1176. '   index of Object
  1177. ' Note:  this method should be used as follows:
  1178. '       Set MyVBOFCollection. _
  1179. '           pvtListBoxTopObject (MyListBox) = _
  1180. '               MyTopObject
  1181.     
  1182.     Dim tempLong As Long
  1183.     
  1184.     On Local Error Resume Next
  1185.     
  1186. ' bullet-proofing
  1187.     If IsMissing(ListBox) Then
  1188.         If pvtListBox Is Nothing Then
  1189.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxTopIndex' method for this object because the 'ListBox' parameter is missing."
  1190.             Exit Property
  1191.         End If
  1192.     Else
  1193.         Set pvtListBox = ListBox
  1194.     End If
  1195.  
  1196.     tempLong = _
  1197.         CollectionIndex(Item:=Object)
  1198.  
  1199.     If tempLong > 0 Then
  1200.         pvtListBox.TopIndex = tempLong + 1
  1201.     End If
  1202. End Property
  1203.  
  1204.  
  1205. Public Property Get pvtListBoxListIndexObject(ListBox As Variant) As Variant
  1206. ' Returns the object at the ListBox's ListIndex
  1207. ' Note:  this method should be coded as follows:
  1208. '   Private Sub MyListBox_Click()
  1209. '       Dim MyObject as MyObject
  1210. '       MyObject = _
  1211. '           MyVBOFCollection.pvtListBoxListIndexObject _
  1212. '               (MyListBox)
  1213. '   End Sub
  1214.  
  1215.     On Local Error Resume Next
  1216.     
  1217. ' bullet-proofing
  1218.     If IsMissing(ListBox) Then
  1219.         If pvtListBox Is Nothing Then
  1220.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxListIndexObject' method for this object because the 'ListBox' parameter is missing."
  1221.             Set pvtListBoxListIndexObject = Nothing
  1222.             Exit Property
  1223.         End If
  1224.     Else
  1225.         Set pvtListBox = ListBox
  1226.     End If
  1227.  
  1228.     If pvtListBox.ListIndex >= 0 _
  1229.     And pvtCollection.Count >= pvtListBox.ListIndex + 1 Then
  1230.         Set pvtListBoxListIndexObject = _
  1231.             pvtCollection.Item(pvtListBox.ListIndex + 1)
  1232.     Else
  1233.         Set pvtListBoxListIndexObject = Nothing
  1234.     End If
  1235.  
  1236. End Property
  1237.  
  1238. Public Property Set pvtListBoxListIndexObject(ListBox As Variant, Object As Variant)
  1239. ' Sets the ListBox's ListIndex to correspond to the
  1240. '   Object and returns the selected Object
  1241. ' Note:  this method should be coded as follows:
  1242. '   Private Sub MyListBox_Click()
  1243. '       Dim MyObject as MyObject
  1244. '       Set MyVBOFCollection.pvtListBoxListIndexObject _
  1245. '               (MyListBox) = MyObject
  1246. '   End Sub
  1247.  
  1248.     On Local Error Resume Next
  1249.     
  1250. ' bullet-proofing
  1251.     If IsMissing(ListBox) Or IsMissing(Object) Then
  1252.         If pvtListBox Is Nothing Then
  1253.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxListIndexObject' method for this object because the 'ListBox' or 'Object' parameter is missing."
  1254.             Exit Property
  1255.         End If
  1256.     Else
  1257.         Set pvtListBox = ListBox
  1258.     End If
  1259.  
  1260.     pvtListBox.ListIndex = _
  1261.         CollectionIndex(Item:=Object)
  1262. End Property
  1263.  
  1264.  
  1265. Public Function pvtListBoxAddItems(Optional ListBox As Variant) As Boolean
  1266. ' Populates the ListBox with one line of information
  1267. '   for each object in this VBOFCollection
  1268. ' Note:  the referenced objects must contain the
  1269. '   method 'ObjectListBoxValue', which must return
  1270. '   a String which is the text which is to appear
  1271. '   in the ListBox and is to represent the object
  1272. '   for the purposes of the ListBox.
  1273. ' Note:  this method should be coded as follows:
  1274. '    MyVBOFCollection.pvtListBoxAddItems MyListBox
  1275.  
  1276.     Dim tempObject As Object
  1277.     Dim tempListBoxText As String
  1278.     Dim tempListBox As Variant
  1279.     
  1280.     On Local Error Resume Next
  1281.     
  1282. ' bullet-proofing
  1283.     If IsMissing(ListBox) Then
  1284.         If pvtListBox Is Nothing Then
  1285.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxAddItems' method for this object because the 'ListBox:=' parameter is missing."
  1286.             pvtListBoxAddItems = False
  1287.             GoTo pvtListBoxAddItems_Exit
  1288.         End If
  1289.     Else
  1290.         Set pvtListBox = ListBox
  1291.     End If
  1292.         
  1293. #If NoDebugMode = False Then
  1294.     If pvtVBOFObjectManager.DebugMode Then
  1295.         pvtVBOFObjectManager.DisplayDebugMessage _
  1296.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has begun '.pvtListBoxAddItems' processing"
  1297.     End If
  1298. #End If
  1299.  
  1300. ' .AddItem each object into the ListBox
  1301.     For Each tempObject In pvtCollection
  1302.         pvtListBox.AddItem _
  1303.             tempObject.ObjectListBoxValue()
  1304.     Next tempObject
  1305.  
  1306.     pvtListBoxAddItems = True
  1307.     GoTo pvtListBoxAddItems_Exit
  1308.  
  1309. pvtListBoxAddItems_Exit:
  1310.     Set tempObject = Nothing
  1311.     Set tempListBox = Nothing
  1312.  
  1313. End Function
  1314.  
  1315. Public Function pvtListBoxClear(Optional ListBox As Variant, Optional NoDelete As Variant) As Boolean
  1316. ' Empties the objects from the ListBox and removes
  1317. '   the corresponding objects from the Collection
  1318. ' Note:  this method should be coded as follows:
  1319. '     MyVBOFCollection.pvtListBoxClear _
  1320. '               MyListBox
  1321. ' Note:
  1322. '   In order to actually remove the containment
  1323. '       links from the containing object to the
  1324. '       items in the ListBox, specify
  1325. '       NoDelete:=False
  1326.  
  1327.     Dim tempObject As Object
  1328.         
  1329.     On Local Error Resume Next
  1330.     
  1331. ' bullet-proofing
  1332.     If IsMissing(ListBox) Then
  1333.         If pvtListBox Is Nothing Then
  1334.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxClear' method for this object because the 'ListBox:=' parameter is missing."
  1335.             pvtListBoxClear = False
  1336.             GoTo pvtListBoxClear_Exit
  1337.         End If
  1338.     Else
  1339.         Set pvtListBox = ListBox
  1340.     End If
  1341.     
  1342. ' clear the ListBox
  1343.     pvtListBox.Clear
  1344.  
  1345. ' .RemoveObject for each object in the Collection
  1346.     If Not IsMissing(NoDelete) Then
  1347.         If Not NoDelete Then     ' doesn't work when ANDed with line above
  1348.             For Each tempObject In pvtCollection
  1349.                 pvtVBOFObjectManager.RemoveObject _
  1350.                     Object:=tempObject, _
  1351.                     Parent:=Me, _
  1352.                     NoDelete:=NoDelete
  1353.             Next tempObject
  1354.         End If
  1355.     End If
  1356.  
  1357.     pvtListBoxClear = True
  1358.     GoTo pvtListBoxClear_Exit
  1359.  
  1360. pvtListBoxClear_Exit:
  1361.     Set tempObject = Nothing
  1362. End Function
  1363. Public Function pvtListBoxRemoveObject(Optional ListBox As Variant, Optional Object As Variant) As Boolean
  1364. ' Removes the specified Object from the ListBox
  1365. ' Note:  this method should be coded as follows:
  1366. '       Dim MyUndesiredObject As MyClass
  1367. '       MyVBOFCollection.pvtListBoxRemoveObject _
  1368. '          MyListBox, MyUndesiredObject
  1369.  
  1370.     Dim tempIndex As Long
  1371.  
  1372.     On Local Error Resume Next
  1373.     
  1374. ' bullet-proofing
  1375.     If IsMissing(ListBox) Then
  1376.         If pvtListBox Is Nothing Then
  1377.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectObject' method for this object because the 'ListBox' parameter is missing."
  1378.             pvtListBoxRemoveObject = False
  1379.             Exit Function
  1380.         End If
  1381.     Else
  1382.         Set pvtListBox = ListBox
  1383.     End If
  1384.     If IsMissing(Object) Then
  1385.         pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectObject' method for this object because the 'Object' parameter is missing."
  1386.         pvtListBoxRemoveObject = False
  1387.         Exit Function
  1388.     End If
  1389.  
  1390. ' find the Object
  1391.     tempIndex = _
  1392.         CollectionIndex(Item:=Object)
  1393.  
  1394.     If tempIndex <= 0 Then
  1395.         pvtListBoxRemoveObject = False
  1396.         Exit Function
  1397.     End If
  1398.  
  1399. ' remove the Object from the Collection
  1400.     Remove _
  1401.         Item:=Object, _
  1402.         NoDelete:=True
  1403.  
  1404. ' remove the Object from the ListBox
  1405.     pvtListBox.RemoveItem _
  1406.         tempIndex - 1
  1407.         
  1408.     pvtListBoxRemoveObject = True
  1409. End Function
  1410.  
  1411.  
  1412.  
  1413. Public Function pvtListBoxRemoveItem(Optional ListBox As Variant, Optional ListIndex As Variant) As Boolean
  1414. ' Removes the Object at the specified ListIndex
  1415. '   from the ListBox
  1416. ' Note:  this method should be coded as follows:
  1417. '       Dim MyUndesiredListIndex As Long
  1418. '       MyVBOFCollection.pvtListBoxRemoveItem _
  1419. '          MyListBox, MyUndesiredListIndex
  1420.  
  1421.     Dim tempObject As Object
  1422.  
  1423.     On Local Error Resume Next
  1424.     
  1425. ' bullet-proofing
  1426.     If IsMissing(ListBox) Then
  1427.         If pvtListBox Is Nothing Then
  1428.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectObject' method for this object because the 'ListBox' parameter is missing."
  1429.             pvtListBoxRemoveItem = False
  1430.             Exit Function
  1431.         End If
  1432.     Else
  1433.         Set pvtListBox = ListBox
  1434.     End If
  1435.     If IsMissing(ListIndex) Then
  1436.         pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectObject' method for this object because the 'ListIndex'  parameter is missing."
  1437.         pvtListBoxRemoveItem = False
  1438.         Exit Function
  1439.     End If
  1440.  
  1441. ' find the Object
  1442.     Set tempObject = _
  1443.         pvtCollection.Item(ListIndex + 1)
  1444.  
  1445.     If tempObject Is Nothing Then
  1446.         pvtListBoxRemoveItem = False
  1447.         Exit Function
  1448.     End If
  1449.  
  1450. ' remove the Object from the Collection
  1451.     Remove _
  1452.         Item:=tempObject, _
  1453.         NoDelete:=True
  1454.  
  1455. ' remove the Object from the ListBox
  1456.     pvtListBox.RemoveItem _
  1457.         ListIndex
  1458.         
  1459.     pvtListBoxRemoveItem = True
  1460.     Set tempObject = Nothing
  1461. End Function
  1462.  
  1463.  
  1464. Public Property Get pvtListBoxSelectedObjects(ListBox As Variant) As Collection
  1465. ' Returns a collection of the selected objects
  1466. '   of the specified ListBox
  1467. ' Note:  this method should be coded as follows:
  1468. '   Private Sub MyListBox_Click()
  1469. '       Dim MyCollection As Collection
  1470. '       Set MyCollection = _
  1471. '           MyVBOFCollection.pvtListBoxSelectedObjects _
  1472. '               (MyListBox)
  1473. '   End Sub
  1474.     
  1475.     Dim tempCollection As New Collection
  1476.     Dim tempObject As Object
  1477.     Dim I As Long
  1478.         
  1479.     On Local Error Resume Next
  1480.     
  1481. ' bullet-proofing
  1482.     If IsMissing(ListBox) Then
  1483.         If pvtListBox Is Nothing Then
  1484.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectedObjects' method for this object because the 'ListBox' parameter is missing."
  1485.             Set pvtListBoxSelectedObjects = Nothing
  1486.             Exit Property
  1487.         End If
  1488.     Else
  1489.         Set pvtListBox = ListBox
  1490.     End If
  1491.  
  1492. ' collect all selected objects
  1493.     I = 0
  1494.     For Each tempObject In pvtCollection
  1495.         If pvtListBox.Selected(I) Then
  1496.             tempCollection.Add tempObject
  1497.         End If
  1498.         
  1499.         I = I + 1
  1500.     Next tempObject
  1501.  
  1502.     Set pvtListBoxSelectedObjects = tempCollection
  1503.     Set tempObject = Nothing
  1504. End Property
  1505.  
  1506.  
  1507. Public Property Set pvtListBoxSelectedObjects(ListBox As Variant, Collection As Collection)
  1508. ' Sets the selected objects of the specified
  1509. '   ListBox to the contents of Collection
  1510. ' Note:  this method should be coded as follows:
  1511. '       Dim MyCollection As Collection
  1512. '       MyVBOFCollection.pvtListBoxSelectedObjects _
  1513. '               (MyListBox) = MyCollection
  1514.     
  1515.     Dim tempObject As Object
  1516.     Dim tempIndex As Long
  1517.     Dim I As Long
  1518.     
  1519.     On Local Error Resume Next
  1520.     
  1521. ' bullet-proofing
  1522.     If IsMissing(ListBox) Or IsMissing(Collection) Then
  1523.         If pvtListBox Is Nothing Then
  1524.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectedObjects' method for this object because the 'ListBox' or 'Collection' parameter is missing."
  1525.             Exit Property
  1526.         End If
  1527.     Else
  1528.         Set pvtListBox = ListBox
  1529.     End If
  1530.  
  1531. ' unselect any currently selected rows
  1532.     For I = 0 To pvtListBox.ListCount - 1
  1533.         pvtListBox.Selected(I) = False
  1534.     Next I
  1535.  
  1536. ' select those rows whose corresponding objects
  1537. '   appear in Collection
  1538.     For Each tempObject In Collection
  1539.         tempIndex = _
  1540.             CollectionIndex(Item:=tempObject)
  1541.             
  1542.         If tempIndex > 0 Then
  1543.             pvtListBox.Selected(tempIndex - 1) = True
  1544.         End If
  1545.         
  1546.     Next tempObject
  1547.     
  1548.     Set tempObject = Nothing
  1549. End Property
  1550.  
  1551.  
  1552.  
  1553.  
  1554. Public Function Add(Optional Item As Variant, Optional Key As Variant, Optional Parent As Variant, Optional After As Variant, Optional NoInsert As Variant) As Variant
  1555. Attribute Add.VB_Description = "Add an item to the collection.  Automatically inserts the item into the associated table.  See the VB Programmer's Manual for details"
  1556. ' Add the new Item to the collection and
  1557. '   return the collection.
  1558. ' Note: Item might be freed by VBOFObjectManager
  1559. '   if it is found to be non-unique throughout the
  1560. '   environment.  For more information, refer to
  1561. '   VBOFObjectManager.AddUniqueObject.
  1562.  
  1563.     Dim tempSuppressInsert As Boolean
  1564.     Dim tempObject As Object
  1565.     Dim tempFoundInFirstPass As Boolean
  1566.  
  1567.     On Local Error Resume Next
  1568.     Set Add = Me
  1569.         
  1570. ' bullet-proofing
  1571.     If Not pvtSetParent( _
  1572.             Parent:=Parent, _
  1573.             MethodName:="Add") Then
  1574.         Set Add = Item
  1575.         GoTo Add_Exit
  1576.     End If
  1577.     If IsMissing(Item) Then
  1578.         pvtErrorMessage TypeName(Me) & " cannot process the '.Add' method for this object because the 'Item:=' parameter is missing."
  1579.         Set Add = Item
  1580.         GoTo Add_Exit
  1581.     End If
  1582.  
  1583. ' support database-free emulation of the VB Collection Class
  1584.     tempSuppressInsert = False
  1585.     If Item.ObjectDataSource = "" _
  1586.     Or Err = 438 Then
  1587.         pvtCollectionEmulationMode = True
  1588.         tempSuppressInsert = True
  1589.     End If
  1590.     If Not IsMissing(NoInsert) Then
  1591.         If NoInsert = True Then
  1592.             tempSuppressInsert = True
  1593.         End If
  1594.     End If
  1595.         
  1596. ' verify that the object is unique across
  1597. '   the known system objects
  1598. '   (First pass.  Works only when adding
  1599. '   Object to a subsequent Collection)
  1600.     tempFoundInFirstPass = False
  1601.     Set tempObject = _
  1602.         pvtVBOFObjectManager. _
  1603.             AddUniqueObject _
  1604.                 (Object:=Item)
  1605.     If Not pvtVBOFObjectManager.ObjectWasUnique Then
  1606.         tempFoundInFirstPass = True
  1607.     End If
  1608.  
  1609. '>>if tempObject= is moved, change tempObject.*
  1610. '   to Item.* down to "where tempObject= used to be"
  1611.  
  1612. ' if in an Insert-capable mode
  1613.     If Not tempSuppressInsert _
  1614.     And Not tempFoundInFirstPass Then
  1615.  
  1616. ' if Item.ObjectID doesn't already have a value
  1617. '   (meaning that it has never been inserted in
  1618. '   the database),
  1619.         If tempObject.ObjectID <= 0 Then
  1620.         
  1621. ' insert Item and set Item.ObjectID
  1622.             Item.ObjectID = _
  1623.                 pvtDBInsert( _
  1624.                     Item:=tempObject)
  1625.         End If
  1626.  
  1627. ' else, if the ObjectID doesn't already have a value
  1628. '   assign an artificial ObjectID
  1629.     ElseIf Not tempFoundInFirstPass Then
  1630.         pvtVBOFObjectManager.HighestObjectID = _
  1631.             pvtVBOFObjectManager.HighestObjectID + 1
  1632.         tempObject.ObjectID = _
  1633.             pvtVBOFObjectManager.HighestObjectID
  1634.     End If
  1635.             
  1636. ' save the HighestObjectID encountered
  1637.     If tempObject.ObjectID > _
  1638.     pvtVBOFObjectManager.HighestObjectID Then
  1639.         pvtVBOFObjectManager. _
  1640.             HighestObjectID = _
  1641.                 tempObject.ObjectID
  1642.     End If
  1643.         
  1644. ' verify that the object is unique across
  1645. '   the known system objects
  1646. '   (Second pass.  Finds redundantly inserted
  1647. '   Objects)
  1648.     If Not tempFoundInFirstPass Then
  1649.         Set tempObject = _
  1650.             pvtVBOFObjectManager. _
  1651.                 AddUniqueObject _
  1652.                     (Object:=tempObject)
  1653.     End If
  1654.  
  1655. ' use the Key:= if it was provided and it was
  1656. '   of Type(Long)
  1657.     If IsMissing(Key) Or Key = 0 Or Err = 13 Then
  1658.         pvtAddItemToCollection _
  1659.             Item:=tempObject, _
  1660.             Key:=CStr(tempObject.ObjectID), _
  1661.             After:=After
  1662.  
  1663. ' else, use the Item.ObjectID
  1664.     Else
  1665.         pvtAddItemToCollection _
  1666.             Item:=tempObject, _
  1667.             Key:=Key, _
  1668.             After:=After
  1669.     End If
  1670.  
  1671. ' link the Item to its Parent object
  1672. '   (in the database)
  1673.     If pvtCollectionEmulationMode = False Then
  1674.         RC = pvtLinkParentToChildObject( _
  1675.                 Parent:=pvtParent, _
  1676.                 Child:=tempObject)
  1677.         
  1678.         pvtRefreshRecordSet
  1679.     End If
  1680.  
  1681. #If NoDebugMode = False Then
  1682.     If pvtVBOFObjectManager.DebugMode Then
  1683.         pvtVBOFObjectManager.DisplayDebugMessage _
  1684.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has added  ObjectType=" & _
  1685.             TypeName(tempObject) & _
  1686.             ", ObjectID=" & _
  1687.             tempObject.ObjectID
  1688.     End If
  1689. #End If
  1690.  
  1691. ' trigger the "Added" event for the new object
  1692. #If NoEventMgr = False Then
  1693.     TriggerCollectionEvent _
  1694.         Object:=tempObject, _
  1695.         Event:="AddedItem"
  1696. #End If
  1697.         
  1698.     Set Add = tempObject
  1699.     GoTo Add_Exit
  1700.  
  1701. Add_Exit:
  1702.     Set pvtMostRecentlyAddedObject = tempObject
  1703.     Set tempObject = Nothing
  1704. End Function
  1705. Private Function pvtLinkParentToChildObject(Optional Parent As Variant, Optional Child As Variant) As Long
  1706.  
  1707.     Dim SQLStatement As String
  1708.     
  1709.     On Local Error Resume Next
  1710.     
  1711.     If pvtCollectionEmulationMode Then
  1712.         pvtLinkParentToChildObject = True
  1713.     End If
  1714.  
  1715. ' insert a row into the VBObjectFrameworkObjectLinks table
  1716.     SQLStatement = _
  1717.         "INSERT INTO " & ObjectDataSource() & " " & _
  1718.         "(FromObjectType" & _
  1719.         ",FromObjectID" & _
  1720.         ",ToObjectType" & _
  1721.         ",ToObjectID"
  1722.     SQLStatement = SQLStatement & _
  1723.         ") VALUES " & _
  1724.         "('" & TypeName(Parent) & "'" & _
  1725.         ", " & Parent.ObjectID & "" & _
  1726.         ",'" & TypeName(Child) & "'" & _
  1727.         ", " & Child.ObjectID & ""
  1728.     SQLStatement = SQLStatement & _
  1729.         ")"
  1730.     
  1731.     pvtDatabase.Execute SQLStatement, pvtODBCPassThrough
  1732.     If Err <> 0 Then '
  1733.         pvtErrorMessage TypeName(Me) & " received a database error while attempting to establish an object containment link (Insert).  SQL=" & SQLStatement
  1734.         pvtLinkParentToChildObject = False
  1735.         Exit Function
  1736.     End If
  1737.         
  1738.     pvtLinkParentToChildObject = True
  1739. End Function
  1740.  
  1741.  
  1742. Public Property Get MostRecentlyAddedObject() As Variant
  1743. Attribute MostRecentlyAddedObject.VB_Description = "Returns the most recently added object"
  1744. ' Returns the Object most recently added to the
  1745. '   VBOFCollection
  1746.  
  1747.     Set MostRecentlyAddedObject = _
  1748.         pvtMostRecentlyAddedObject
  1749.  
  1750. End Property
  1751.  
  1752. Public Property Get MostRecentlyAddedObjectIndex() As Long
  1753. Attribute MostRecentlyAddedObjectIndex.VB_Description = "Returns the collection index of the most recently added object"
  1754. ' Returns the Index in the Collection of the
  1755. '   Object most recently added to the
  1756. '   VBOFCollection
  1757.  
  1758.     MostRecentlyAddedObjectIndex = _
  1759.         CollectionIndex _
  1760.             (Item:=pvtMostRecentlyAddedObject)
  1761.  
  1762. End Property
  1763.  
  1764.  
  1765.  
  1766. Public Function pvtCloneRecordSet() As RecordSet
  1767. Attribute pvtCloneRecordSet.VB_Description = "Returns a Clone of the internally maintained RecordSet object"
  1768.     Set pvtCloneRecordSet = pvtRecordSet.Clone()
  1769. End Function
  1770.  
  1771. Public Function CollectionIndex(Optional Item As Variant, Optional Key As Variant, Optional WhereClause As Variant, Optional FindFirst As Variant, Optional FindNext As Variant, Optional FindLast As Variant, Optional FindPrevious As Variant, Optional Collection As Variant) As Long
  1772. Attribute CollectionIndex.VB_Description = "Returns the index (1 - n) of the item in the collection"
  1773. ' Returns the Collection Index of the
  1774. '   specified Item, or the item at the specified Key
  1775. ' Program Usage:
  1776. '   Dim MyCollection as VBOFCollection
  1777. '   MyIndex = MyCollection.CollectionIndex _
  1778. '                (Item:=MyObject)
  1779. ' or
  1780. '   MyIndex = MyCollection.CollectionIndex _
  1781. '                (Key:=MyKey)
  1782. ' or
  1783. '   MyIndex = MyCollection.CollectionIndex _
  1784. '                (WhereClause:="LastName = 'Jones'")
  1785. '       (see comments in method "pvtCollectionIndexForWhereClause"
  1786. '       for important information about using the
  1787. '       WhereClause:= parameter)
  1788. ' or
  1789. '   MyIndex = MyCollection.CollectionIndex _
  1790. '                (WhereClause:="LastName = 'Jones'", _
  1791. '                 FindFirst:=True)
  1792. '       (see comments in method "pvtCollectionIndexForWhereClause"
  1793. '       for important information about using the
  1794. '       WhereClause:= parameter)
  1795. '
  1796. ' Parameters:
  1797. '   Item - the object whose Collection Index is
  1798. '       desired
  1799. '   Key - the key value of the object whose
  1800. '       Collection Index is desired
  1801. '   WhereClause - a search string which can be
  1802. '       appended to the RecordSet.FindNext method
  1803. '   FindNext - a boolean which determines whether
  1804. '       the FindNext method should be used
  1805. '       (FindNext is the default)
  1806. '   FindFirst - a boolean which determines whether
  1807. '       the FindFirst method should be used
  1808. '       (FindNext is the default)
  1809. '   FindLast - a boolean which determines whether
  1810. '       the FindLast method should be used
  1811. '       (FindNext is the default)
  1812. '   FindPrevious - a boolean which determines whether
  1813. '       the FindPrevious method should be used
  1814. '       (FindNext is the default)
  1815.  
  1816.     Dim tempItem As Object
  1817.     Dim I As Long
  1818.  
  1819.     On Local Error Resume Next
  1820.     
  1821. ' bullet-proofing
  1822.     If IsMissing(Item) _
  1823.     And IsMissing(Key) _
  1824.     And IsMissing(WhereClause) Then
  1825.         pvtErrorMessage TypeName(Me) & " cannot process the '.CollectionIndex' method for this object because the 'Item:=', 'Key:=' and 'WhereClause:=' parameters are missing."
  1826.         CollectionIndex = -1
  1827.         GoTo CollectionIndex_Exit
  1828.     End If
  1829.     
  1830. ' branch to an appropriate private method
  1831.     If Not IsMissing(Item) Then
  1832.         CollectionIndex = _
  1833.             pvtCollectionIndexForItem( _
  1834.                 Item:=Item, _
  1835.                 Collection:=Collection)
  1836.     ElseIf Not IsMissing(Key) Then
  1837.         CollectionIndex = _
  1838.             pvtCollectionIndexForKey( _
  1839.                 Key:=Key, _
  1840.                 Collection:=Collection)
  1841.     ElseIf Not IsMissing(WhereClause) Then
  1842.         CollectionIndex = _
  1843.             pvtCollectionIndexForWhereClause( _
  1844.                 WhereClause:=WhereClause, _
  1845.                 FindFirst:=FindFirst, _
  1846.                 FindLast:=FindLast, _
  1847.                 FindNext:=FindNext, _
  1848.                 FindPrevious:=FindPrevious)
  1849.     Else
  1850.         CollectionIndex = -1
  1851.     End If
  1852.  
  1853.     GoTo CollectionIndex_Exit
  1854.     
  1855. CollectionIndex_Exit:
  1856.     Set tempItem = Nothing
  1857. End Function
  1858.  
  1859.  
  1860. Private Function pvtCollectionIndexForItem(Optional Item As Variant, Optional Collection As Variant) As Long
  1861. ' Returns the Collection Index of the
  1862. '   specified Item
  1863.  
  1864.     Dim tempItem As Object
  1865.     Dim I As Long
  1866.     Dim tempCollection As Collection
  1867.  
  1868.     On Local Error Resume Next
  1869.     
  1870. ' bullet-proofing
  1871.     If IsMissing(Item) Then
  1872.         pvtErrorMessage TypeName(Me) & " cannot process the '.pvtCollectionIndexForItem' method for this object because the 'Item:=' parameter is missing."
  1873.         pvtCollectionIndexForItem = -1
  1874.         Exit Function
  1875.     End If
  1876.     If Not IsMissing(Collection) Then
  1877.         Set tempCollection = Collection
  1878.     Else
  1879.         Set tempCollection = pvtCollection
  1880.     End If
  1881.     
  1882. ' search each Object in the Collection
  1883.     I = 1
  1884.     For Each tempItem In tempCollection
  1885.         If CStr(tempItem.ObjectID) = CStr(Item.ObjectID) Then
  1886.             If Err = 0 Then ' <=== VB4 Error: for some reason this doesn't work if placed in the above statement as an "And"
  1887.                 pvtCollectionIndexForItem = I
  1888.                 GoTo pvtCollectionIndexForItem_Exit
  1889.             End If
  1890.         End If
  1891.         
  1892.         I = I + 1
  1893.     Next tempItem
  1894.  
  1895.     pvtCollectionIndexForItem = -1
  1896.     GoTo pvtCollectionIndexForItem_Exit
  1897.     
  1898. pvtCollectionIndexForItem_Exit:
  1899.     Set tempItem = Nothing
  1900. End Function
  1901.  
  1902. Private Function pvtCollectionIndexForKey(Optional Key As Variant, Optional Collection As Variant) As Long
  1903. ' Returns the Collection Index of the Item at the
  1904. '   specified Key
  1905.  
  1906.     Dim tempItem As Object
  1907.     Dim I As Long
  1908.     Dim tempCollection As Collection
  1909.  
  1910.     On Local Error Resume Next
  1911.     
  1912. ' bullet-proofing
  1913.     If IsMissing(Key) Then
  1914.         pvtErrorMessage TypeName(Me) & " cannot process the '.pvtCollectionIndexForKey' method for this object because the 'Key:=' parameter is missing."
  1915.         pvtCollectionIndexForKey = -1
  1916.         Exit Function
  1917.     End If
  1918.     If Not IsMissing(Collection) Then
  1919.         Set tempCollection = Collection
  1920.     Else
  1921.         Set tempCollection = pvtCollection
  1922.     End If
  1923.     
  1924.     I = 1
  1925.     For Each tempItem In tempCollection
  1926.         If CStr(tempItem.ObjectID) = CStr(Key) Then
  1927.             If Err = 0 Then ' <=== VB4 Error: for some reason this doesn't work if placed in the above statement as an "And"
  1928.                 pvtCollectionIndexForKey = I
  1929.                 GoTo pvtCollectionIndexForKey_Exit
  1930.             End If
  1931.         End If
  1932.         
  1933.         I = I + 1
  1934.     Next tempItem
  1935.  
  1936.     pvtCollectionIndexForKey = -1
  1937.     GoTo pvtCollectionIndexForKey_Exit
  1938.     
  1939. pvtCollectionIndexForKey_Exit:
  1940.     Set tempItem = Nothing
  1941. End Function
  1942.  
  1943.  
  1944.  
  1945. Public Function Count() As Long
  1946. Attribute Count.VB_Description = "Returns a count of the number of items currently in the collection.  See the VB Programmer's Manual for details"
  1947. ' Returns the count of objects currently defined
  1948. '   as part of the collection
  1949.  
  1950.     Count = pvtCollection.Count
  1951. End Function
  1952.  
  1953. Public Property Get Database() As Database
  1954. Attribute Database.VB_Description = "Sets the database property"
  1955.     Set Database = pvtDatabase
  1956. End Property
  1957.  
  1958. Public Property Set Database(Database As Database)
  1959.  
  1960.     If Not IsMissing(Database) Then
  1961.         pvtReceiveGeneralParameters _
  1962.             Database:=Database
  1963.             
  1964.         pvtCollectionEmulationMode = False
  1965.     End If
  1966.  
  1967. End Property
  1968.  
  1969.  
  1970. Public Function pvtDatabaseHasBeenReferenced() As Boolean
  1971. Attribute pvtDatabaseHasBeenReferenced.VB_Description = "Returns turue or false, depending on whether or not the DBAwareCollection has referenced the database to attempt to instantiate the collection of contained objects"
  1972. ' Returns aBoolean, depending on whether or not the
  1973. '   Database has been referenced as of yet for this
  1974. '   VBOFCollection
  1975.     
  1976.     pvtDatabaseHasBeenReferenced = _
  1977.         pvtDBHasBeenReferenced
  1978. End Function
  1979.  
  1980. Private Function pvtPopulateFromDatabase(Optional Database As Variant, Optional Sample As Variant, Optional Parent As Variant, Optional WhereClause As Variant, Optional SQL As Variant, Optional OrderByClause As Variant, Optional ANSISQL As Variant, Optional ODBCPassThrough As Variant) As VBOFCollection
  1981. Attribute pvtPopulateFromDatabase.VB_Description = "Returns a DBAwareCollection which has been instantiated with a collection of instantiated objects, according to the contents of the associated table"
  1982. ' Returns a VBOFCollection of objects which have been
  1983. '   populated from data found in a database
  1984. '   table meeting the criteria specified in any of
  1985. '   the following methods:
  1986. '       a complete SQL statement can be provided;
  1987. '       a Where Clause can be provided;
  1988. '       a Parent Object can be provided
  1989. '
  1990. ' Parameter Description:
  1991. '       see VBOFObjetManager.ManageCollection
  1992.  
  1993.     Dim tempRow As Object
  1994.     Dim newChildObject As Object
  1995.     Dim tempIndex As Long
  1996.     
  1997.     On Local Error Resume Next
  1998.     
  1999.     Set pvtPopulateFromDatabase = Nothing
  2000.     pvtRecordSetProvidedByUser = False
  2001.  
  2002. ' test Sample for Database-readiness
  2003.     If Not IsMissing(Sample) Then
  2004.         If (Sample.ObjectDataSource = "" _
  2005.         Or Err = 438) Then
  2006.             pvtCollectionEmulationMode = True
  2007.         End If
  2008.     End If
  2009.  
  2010.     pvtReceiveGeneralParameters _
  2011.         Database:=Database, _
  2012.         Sample:=Sample, _
  2013.         Parent:=Parent, _
  2014.         WhereClause:=WhereClause, _
  2015.         OrderByClause:=OrderByClause, _
  2016.         ANSISQL:=ANSISQL, _
  2017.         ODBCPassThrough:=ODBCPassThrough, _
  2018.         SQL:=SQL
  2019.  
  2020. ' determine the usability of the parameters
  2021.     If Not pvtIsDatabaseSpecified() _
  2022.     Or Not pvtIsSQLAccessable() _
  2023.     Then
  2024.         Exit Function
  2025.     End If
  2026.  
  2027. ' open a RecordSet containing the desired rows
  2028.     Set pvtRecordSet = _
  2029.         pvtDBSelect(pvtCreateSQLStatement())
  2030.  
  2031. ' create the objects from the contents of the
  2032. '   RecordSet
  2033.     
  2034.     Set pvtCollection = _
  2035.         pvtInstantiateObjectsFromRecordSet( _
  2036.             RecordSet:=pvtRecordSet, _
  2037.             Collection:=pvtCollection)
  2038.  
  2039. pvtPopulateFromDatabase_Exit:
  2040. #If NoDebugMode = False Then
  2041.     If pvtVBOFObjectManager.DebugMode Then
  2042.         pvtVBOFObjectManager.DisplayDebugMessage _
  2043.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has instantiated a collection of objects from the Database.  " & _
  2044.             "Object count=" & pvtCollection.Count & ", ParentType=" & _
  2045.             TypeName(Parent) & ", ObjectID=" & _
  2046.             Parent.ObjectID & ", ChildObjectType=" & _
  2047.             TypeName(Sample)
  2048.     End If
  2049. #End If
  2050.  
  2051. ' trigger the "PopulatedFromDatabase" event for Me
  2052. #If NoEventMgr = False Then
  2053.     TriggerCollectionEvent _
  2054.         Event:="PopulatedFromDatabase"
  2055. #End If
  2056.  
  2057.     Set pvtPopulateFromDatabase = Me
  2058.     Set tempRow = Nothing
  2059.     Set newChildObject = Nothing
  2060. End Function
  2061.  
  2062.  
  2063. Private Sub pvtDBGridBookmarkArrayClear()
  2064.  
  2065.     ReDim Preserve _
  2066.         pvtDBGridBookmarkArray(1 To 2, 0)
  2067.     
  2068.     pvtDBGridBookmarkArrayAvailable = False
  2069. End Sub
  2070.  
  2071. Public Function Item(Optional ObjectID As Variant) As Variant
  2072. Attribute Item.VB_Description = "Returns either the entire VBOFCollection (as a collection) or a specific item.  See the VB Programmer's Manual for details"
  2073. ' Returns either the entire collection or a
  2074. '   specific item in the collection
  2075. ' As with the standard VB Collection object,
  2076. '   if Item:= is specified, then the requested
  2077. '   object is returned (if it can be found),
  2078. '   otherwise the entire collection is returned
  2079.  
  2080.     On Local Error Resume Next
  2081.  
  2082. ' determine the usability of the current state
  2083.     If Not pvtCollectionEmulationMode Then
  2084.         If Not pvtIsDatabaseSpecified() _
  2085.         Or Not pvtIsSQLAccessable() _
  2086.         Or Not pvtIsCollectionInstantiated() _
  2087.         Then
  2088.             Exit Function
  2089.         End If
  2090.     End If
  2091.     
  2092. ' check for a request for a specific Object
  2093.     If Not IsMissing(ObjectID) Then
  2094.         Set Item = pvtCollection.Item(ObjectID)
  2095.         If Err = 5 Then
  2096.             Set Item = Nothing
  2097.             Exit Function
  2098.         End If
  2099.     Else
  2100.         Set Item = Me
  2101.     End If
  2102. End Function
  2103.  
  2104.  
  2105.  
  2106. Public Property Get pvtListBoxSelectObject(ListBox As Variant) As Variant
  2107. ' Returns the selected object from the ListBox
  2108. ' Note:  this method should be coded as follows:
  2109. '       Dim MyDesiredObject As MyClass
  2110. '       Set MyDesiredObject = _
  2111. '           MyVBOFCollection.pvtListBoxSelectObject _
  2112. '               (MyListBox)
  2113.  
  2114.     Dim tempIndex As Long
  2115.     Dim tempObject As Object
  2116.     Dim tempCollection As Collection
  2117.  
  2118.     On Local Error Resume Next
  2119.     
  2120. ' bullet-proofing
  2121.     If IsMissing(ListBox) Then
  2122.         If pvtListBox Is Nothing Then
  2123.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectObject' method for this object because the 'ListBox' or 'Collection' parameter is missing."
  2124.             Set pvtListBoxSelectObject = Nothing
  2125.             Exit Property
  2126.         End If
  2127.     Else
  2128.         Set pvtListBox = ListBox
  2129.     End If
  2130.  
  2131.     Set tempCollection = _
  2132.         pvtListBoxSelectedObjects(pvtListBox)
  2133.         
  2134.     If tempCollection.Count >= 1 Then
  2135.         Set pvtListBoxSelectObject = _
  2136.             tempCollection.Item(1)
  2137.     Else
  2138.         Set pvtListBoxSelectObject = _
  2139.             Nothing
  2140.     End If
  2141.  
  2142.     Set tempObject = Nothing
  2143. End Property
  2144.  
  2145. Public Property Set pvtListBoxSelectObject(ListBox As Variant, Object As Variant)
  2146. ' Selects the specified Object from the ListBox
  2147. ' Note:  this method should be coded as follows:
  2148. '       Dim MyDesiredObject As MyClass
  2149. '       MyVBOFCollection.pvtListBoxSelectObject _
  2150. '               (MyListBox) = MyDesiredObject
  2151.  
  2152.     Dim tempIndex As Long
  2153.     
  2154. ' bullet-proofing
  2155.     If IsMissing(ListBox) Or IsMissing(Object) Then
  2156.         If pvtListBox Is Nothing Then
  2157.             pvtErrorMessage TypeName(Me) & " cannot process the '.pvtListBoxSelectObject' method for this object because the 'ListBox' or 'Object' parameter is missing."
  2158.             Exit Property
  2159.         End If
  2160.     Else
  2161.         Set pvtListBox = ListBox
  2162.     End If
  2163.  
  2164.     If Object Is Nothing Then
  2165.         Exit Property
  2166.     End If
  2167.  
  2168. ' find Object in the collection
  2169.     tempIndex = _
  2170.         CollectionIndex(Item:=Object)
  2171.             
  2172. ' handle 'Not Found'
  2173.     If tempIndex <= 0 Then
  2174.         Exit Property
  2175.     End If
  2176.  
  2177. ' select the corresponding ListBox item
  2178.     pvtListBox.Selected(tempIndex - 1) = True
  2179.     
  2180. End Property
  2181.  
  2182.  
  2183.  
  2184. Public Property Set ObjectManager(anObjectManager As VBOFObjectManager)
  2185. ' Set my reference to the VBOFObjectManager
  2186. '   and register for Collection Events
  2187.     
  2188.     Set pvtVBOFObjectManager = anObjectManager
  2189.     
  2190. #If NoEventMgr = False Then
  2191.     pvtVBOFObjectManager. _
  2192.         RegisterForCollectionEvent _
  2193.         RegisterObject:=Me
  2194. #End If
  2195. End Property
  2196.  
  2197.  
  2198. Public Property Get Parent()
  2199. Attribute Parent.VB_Description = "Sets the Parent property"
  2200. ' Returns the most recently specified
  2201. '   Parent:= object
  2202.  
  2203.     Set Parent = pvtParent
  2204. End Property
  2205.  
  2206. Private Function pvtAddItemToCollection(Optional Item As Variant, Optional Key As Variant, Optional After As Variant) As Collection
  2207. Attribute pvtAddItemToCollection.VB_Description = "(Private) adds an item to the internally managed collection"
  2208. ' Return the VBOFCollection after having added
  2209. '   Item.  Take into account the impact of the
  2210. '   After parameter
  2211.  
  2212.     Dim tempAfter As Long
  2213.     Dim tempCollectionIndex As Long
  2214.     
  2215.     On Local Error Resume Next
  2216.     
  2217. ' set default After value
  2218.     tempAfter = pvtCollection.Count
  2219.     
  2220. ' use any specified After value
  2221.     If Not IsMissing(After) Then
  2222.         If After <= pvtCollection.Count Then
  2223.             tempAfter = After
  2224.         End If
  2225.     End If
  2226.     
  2227. ' insert somewhere after the first item
  2228.     If tempAfter > 0 Then
  2229.         pvtCollection.Add _
  2230.             Item:=Item, _
  2231.             Key:=CStr(Item.ObjectID), _
  2232.             After:=tempAfter
  2233.             
  2234. ' insert before the first item
  2235.     ElseIf pvtCollection.Count > 0 Then
  2236.         pvtCollection.Add _
  2237.             Item:=Item, _
  2238.             Key:=CStr(Item.ObjectID), _
  2239.             Before:=1
  2240.             
  2241. ' insert as the first item
  2242.     Else
  2243.         pvtCollection.Add _
  2244.             Item:=Item, _
  2245.             Key:=CStr(Item.ObjectID)
  2246.     End If
  2247.  
  2248. ' add the reference to the pvtDBGridBookmarkArray
  2249.     If Err = 0 Then
  2250.         pvtAddItemToDBGridArray _
  2251.             Item:=Item
  2252.     End If
  2253.  
  2254.     Set pvtAddItemToCollection = _
  2255.         pvtCollection
  2256. End Function
  2257.  
  2258. Private Sub pvtAddItemToDBGridArray(Optional Item As Variant, Optional Collection As Variant)
  2259. ' Add the Item to the pvtDBGridBookmarkArray
  2260.  
  2261.     Dim tempCollectionIndex As Long
  2262.  
  2263.     tempCollectionIndex = _
  2264.         CollectionIndex( _
  2265.             Item:=Item, _
  2266.             Collection:=Collection)
  2267.             
  2268.     If tempCollectionIndex > 0 Then
  2269.         pvtDBGridBookmarkArrayAdd _
  2270.             tempCollectionIndex - 1, _
  2271.             tempCollectionIndex - 1, _
  2272.             CStr(Item.ObjectID)
  2273.     End If
  2274. 'DebugpvtDBGridBookmarkArray
  2275. End Sub
  2276.  
  2277. Private Function pvtBuildSQLStatementFromWhereClause(Optional WhereClause As Variant) As String
  2278. Attribute pvtBuildSQLStatementFromWhereClause.VB_Description = "(Private) returns an SQL Select statement which includes a user-specified Where clause.  The SQL statement should be appropriate for retrieving all of the items contained within the specified parent object"
  2279. ' Return an SQL Statement which uses WhereClause to
  2280. '   select the desired rows
  2281.     
  2282.     Dim SQLStatement As String
  2283.     
  2284.     On Local Error Resume Next
  2285.     
  2286. ' ask the Sample for certain critical services
  2287.     pvtSampleTableName = pvtSample.ObjectDataSource
  2288.     If Err = pvtReceiverDoesNotSupportThisMethod Then
  2289.         pvtErrorMessage "Class Module '" & TypeName(pvtSample) & "' does not support the method 'TableName'." & vbCrLf & "Object cannot be supported by " & TypeName(Me) & " without this method."
  2290.     End If
  2291.  
  2292.     pvtSampleType = TypeName(pvtSample)
  2293. '    If Err = pvtReceiverDoesNotSupportThisMethod Then
  2294. '        pvtErrorMessage "Class Module '" & TypeName(pvtSample) & "' does not support the method 'ObjectType'." & vbCrLf & "Object cannot be supported by " & TypeName(Me) & " without this method."
  2295. '    End If
  2296.     
  2297.     On Local Error Resume Next
  2298.     
  2299.     SQLStatement = _
  2300.         "SELECT DISTINCTROW " & _
  2301.         pvtSampleTableName & ".* FROM " & _
  2302.         pvtSampleTableName & " WHERE " & _
  2303.         WhereClause
  2304.     SQLStatement = SQLStatement & _
  2305.         pvtConcatenateOrderByClause( _
  2306.             SQL:=SQLStatement, _
  2307.             OrderByClause:=pvtOrderByClause)
  2308.        
  2309.     pvtBuildSQLStatementFromWhereClause = SQLStatement
  2310. End Function
  2311.  
  2312.  
  2313. Private Function pvtBuildSQLStatementFromParent(Optional Parent As Variant) As String
  2314. Attribute pvtBuildSQLStatementFromParent.VB_Description = "(Private) returns an SQL Select statement which can be used to retrieve all of the items contained within the specified parent object"
  2315. ' Returns an SQL Statement which retrieves rows
  2316. '   of the child table based on the value of
  2317. '   the Parent object.  If a WhereClause has been
  2318. '   specified, it is appended to the end of the
  2319. '   standard SQL statement for object containment.
  2320.     
  2321.     Dim SQLStatement As String
  2322.     
  2323.     If Not pvtSetParent( _
  2324.             Parent:=Parent, _
  2325.             MethodName:="pvtBuildSQLStatementFromParent") Then
  2326.         pvtBuildSQLStatementFromParent = ""
  2327.         Exit Function
  2328.     End If
  2329.     
  2330.     SQLStatement = _
  2331.         pvtBuildSQLStatementFromParentCode( _
  2332.             Sample:=pvtSample, _
  2333.             Parent:=pvtParent)
  2334.     
  2335. ' concatenate the supplemental Where Clause
  2336.     If pvtWhereClause <> "" Then
  2337.         SQLStatement = SQLStatement & _
  2338.             " AND " & pvtWhereClause
  2339.     End If
  2340.     
  2341. ' concatenate the OrderBy Clause
  2342.     SQLStatement = SQLStatement & _
  2343.         pvtConcatenateOrderByClause( _
  2344.             SQL:=SQLStatement, _
  2345.             OrderByClause:=pvtOrderByClause)
  2346.        
  2347.     pvtBuildSQLStatementFromParent = SQLStatement
  2348. End Function
  2349.  
  2350. Private Function pvtBuildSQLStatementFromParentCode(Optional Parent As Variant, Optional Sample As Variant) As String
  2351. ' Returns an SQL Statement which retrieves rows
  2352. '   of the child table based on the value of
  2353. '   the Parent object.  If a WhereClause has been
  2354. '   specified, it is appended to the end of the
  2355. '   standard SQL statement for object containment.
  2356.     
  2357.     Dim SQLStatement As String
  2358.         
  2359.     On Local Error Resume Next
  2360.     
  2361. ' ask the Sample for certain critical services
  2362.     pvtSampleTableName = _
  2363.         Sample.ObjectDataSource
  2364.     pvtSampleType = _
  2365.         TypeName(Sample)
  2366.     pvtParentTableName = _
  2367.         Parent.ObjectDataSource
  2368.     pvtParentType = _
  2369.         TypeName(Parent)
  2370.     
  2371. ' (SQL Statement modeled in MS Access)
  2372. 'SELECT DISTINCTROW
  2373. '       Persons.* FROM (VBObjectFrameworkObjectLinks INNER JOIN
  2374. '       Company ON VBObjectFrameworkObjectLinks.FromObjectID =
  2375. '       Company.ObjectID) INNER JOIN
  2376. '       Persons ON VBObjectFrameworkObjectLinks.ToObjectID =
  2377. '       Persons.ObjectID WHERE ((VBObjectFrameworkObjectLinks.FromObjectType="
  2378. '       Company") AND (VBObjectFrameworkObjectLinks.ToObjectType="
  2379. '       Person") AND (
  2380. '       Company.ObjectID=
  2381. '       1));
  2382.     If Not pvtANSISQL Then
  2383.         SQLStatement = _
  2384.             "SELECT DISTINCTROW " & _
  2385.             pvtSampleTableName & ".* FROM (" & ObjectDataSource() & " INNER JOIN " & _
  2386.             pvtParentTableName & " ON " & ObjectDataSource() & ".FromObjectID = " & _
  2387.             pvtParentTableName & ".ObjectID) INNER JOIN " & _
  2388.             pvtSampleTableName & " ON " & ObjectDataSource() & ".ToObjectID = " & _
  2389.             pvtSampleTableName & ".ObjectID WHERE ((" & ObjectDataSource() & ".FromObjectType='"
  2390.         SQLStatement = SQLStatement & _
  2391.             pvtParentType & "') AND (" & ObjectDataSource() & ".ToObjectType='" & _
  2392.             pvtSampleType & "') AND (" & _
  2393.             pvtParentTableName & ".ObjectID=" & _
  2394.             CStr(Parent.ObjectID) & "))"
  2395.     Else
  2396.         SQLStatement = _
  2397.             "SELECT " & _
  2398.             pvtSampleTableName & ".* FROM " & _
  2399.             pvtSampleTableName & ", " & _
  2400.             pvtParentTableName & ", " & _
  2401.             ObjectDataSource() & " "
  2402.         SQLStatement = SQLStatement & _
  2403.             "WHERE " & _
  2404.             ObjectDataSource() & ".FromObjectID = " & _
  2405.             pvtParentTableName & ".ObjectID AND " & _
  2406.             ObjectDataSource() & ".ToObjectID = " & _
  2407.             pvtSampleTableName & ".ObjectID "
  2408.         SQLStatement = SQLStatement & _
  2409.             "AND " & _
  2410.             ObjectDataSource() & ".FromObjectType='" & _
  2411.             pvtParentType & "' AND " & ObjectDataSource() & ".ToObjectType='" & _
  2412.             pvtSampleType & "' AND " & _
  2413.             pvtParentTableName & ".ObjectID=" & _
  2414.             CStr(Parent.ObjectID)
  2415.     End If
  2416.        
  2417.     pvtBuildSQLStatementFromParentCode = SQLStatement
  2418. End Function
  2419.  
  2420.  
  2421. Private Sub pvtDBGridBookmarkArrayAdd(RowIndex As Long, Bookmark As Variant, ObjectID As Variant)
  2422. ' Adds an Object / DBGrid Row cross-reference element
  2423.     
  2424.     Dim tempMaxIndex As Long
  2425.     Dim I As Long
  2426.     
  2427.     On Local Error GoTo pvtDBGridBookmarkArrayAdd_Exit
  2428.     
  2429.     tempMaxIndex = UBound(pvtDBGridBookmarkArray, 2)
  2430.     
  2431. ' if adding the new RowIndex at the end
  2432.     If RowIndex > tempMaxIndex _
  2433.     Or Not pvtDBGridBookmarkArrayAvailable Then
  2434.         ReDim Preserve _
  2435.             pvtDBGridBookmarkArray( _
  2436.                 1 To 2, _
  2437.                 0 To RowIndex)
  2438.  
  2439. ' if adding somewhere in the middle
  2440.     Else
  2441.         ReDim Preserve _
  2442.             pvtDBGridBookmarkArray( _
  2443.                 1 To 2, _
  2444.                 0 To tempMaxIndex + 1)
  2445.     End If
  2446.  
  2447. ' up-shift the lower-position entries
  2448.     For I = UBound(pvtDBGridBookmarkArray, 2) - 1 _
  2449.     To RowIndex Step -1
  2450.         pvtDBGridBookmarkArray(1, I + 1) = _
  2451.             pvtDBGridBookmarkArray(1, I)
  2452.         
  2453.         pvtDBGridBookmarkArray(2, I + 1) = _
  2454.             pvtDBGridBookmarkArray(2, I)
  2455.     Next I
  2456.         
  2457.     pvtDBGridBookmarkArrayAvailable = True
  2458.     
  2459.     pvtDBGridBookmarkArray(1, RowIndex) = CStr(Bookmark)
  2460.     pvtDBGridBookmarkArray(2, RowIndex) = ObjectID
  2461. pvtDBGridBookmarkArrayAdd_Exit:
  2462.     Exit Sub
  2463. End Sub
  2464.  
  2465.  
  2466. Private Sub pvtDBGridBookmarkArrayDeleteBookmark(Bookmark As Variant)
  2467.  
  2468.     Dim tempRowIndex As Long
  2469.  
  2470.     tempRowIndex = _
  2471.         pvtDBGridRowIndexAtBookmark(Bookmark)
  2472.  
  2473.     If tempRowIndex >= 0 Then
  2474.         pvtDBGridBookmarkArrayDeleteRowIndex _
  2475.           (tempRowIndex)
  2476.     End If
  2477.  
  2478. End Sub
  2479.  
  2480. Private Sub pvtDBGridBookmarkArrayDeleteRowIndex(RowIndex As Long)
  2481. ' Deletes an Object / DBGrid Row cross-reference
  2482. '   element by its RowIndex
  2483.  
  2484.     Dim I As Long
  2485.     
  2486.     For I = RowIndex To _
  2487.     UBound(pvtDBGridBookmarkArray, 2) - 1
  2488.         pvtDBGridBookmarkArray(1, I) = _
  2489.             pvtDBGridBookmarkArray(1, I + 1)
  2490.     
  2491.         pvtDBGridBookmarkArray(2, I) = _
  2492.             pvtDBGridBookmarkArray(2, I + 1)
  2493.     Next I
  2494.  
  2495.     ReDim Preserve pvtDBGridBookmarkArray( _
  2496.         1 To 2, _
  2497.         0 To UBound(pvtDBGridBookmarkArray, 2) - 1)
  2498. End Sub
  2499.  
  2500.  
  2501.  
  2502.  
  2503. Private Function pvtDBGridBookmarkAtRowIndex(RowIndex As Long) As Variant
  2504.  
  2505.     pvtDBGridBookmarkAtRowIndex = _
  2506.         pvtDBGridBookmarkArray _
  2507.                     (1, RowIndex)
  2508. End Function
  2509.  
  2510.  
  2511. Private Function pvtDBGridObjectIDAtBookmark(Bookmark As Variant) As Variant
  2512.  
  2513.     On Local Error GoTo pvtDBGridObjectIDAtBookmark_Error
  2514.  
  2515.     pvtDBGridObjectIDAtBookmark = _
  2516.         pvtDBGridBookmarkArray( _
  2517.             2, _
  2518.             pvtDBGridRowIndexAtBookmark(Bookmark))
  2519.  
  2520. pvtDBGridObjectIDAtBookmark_Error:
  2521.     Exit Function
  2522. End Function
  2523.  
  2524.  
  2525.  
  2526. Private Function pvtDBGridObjectIDAtRowIndex(RowIndex As Long) As Variant
  2527.  
  2528.     pvtDBGridObjectIDAtRowIndex = _
  2529.         pvtDBGridBookmarkArray _
  2530.                     (2, RowIndex)
  2531. End Function
  2532.  
  2533.  
  2534. Private Function pvtDBGridRowIndexAtBookmark(Bookmark As Variant) As Long
  2535.  
  2536.     On Local Error GoTo pvtDBGridRowIndexAtBookmark_Error
  2537.  
  2538.     Dim I As Long
  2539.     
  2540.     For I = 0 _
  2541.     To UBound(pvtDBGridBookmarkArray, 2)
  2542.         If pvtDBGridBookmarkArray(1, I) = Bookmark Then
  2543.             pvtDBGridRowIndexAtBookmark = I
  2544.             Exit Function
  2545.         End If
  2546.     Next I
  2547.  
  2548. pvtDBGridRowIndexAtBookmark_Error:
  2549.     pvtDBGridRowIndexAtBookmark = -1
  2550.     Exit Function
  2551. End Function
  2552.  
  2553.  
  2554. Private Function pvtDBGridRowIndexAtObjectID(ObjectID As Variant) As Long
  2555.  
  2556.     Dim I As Long
  2557.     
  2558.     For I = 0 _
  2559.     To UBound(pvtDBGridBookmarkArray, 2)
  2560.         If pvtDBGridBookmarkArray(2, I) = ObjectID Then
  2561.             pvtDBGridRowIndexAtObjectID = I
  2562.             Exit Function
  2563.         End If
  2564.     Next I
  2565.  
  2566.     pvtDBGridRowIndexAtObjectID = -1
  2567. End Function
  2568.  
  2569.  
  2570. Private Function pvtDBGridGetRelativeBookmark(Bookmark As Variant, Increment As Long, MaxRow As Long) As Variant
  2571.  
  2572.     Dim I As Long
  2573.     
  2574.     I = pvtDBGridIndexFromBookmark _
  2575.             (Bookmark, False, MaxRow) + _
  2576.             Increment
  2577.     If I < 0 Or I >= MaxRow Then
  2578.         pvtDBGridGetRelativeBookmark = Null
  2579.     Else
  2580.         pvtDBGridGetRelativeBookmark = _
  2581.             pvtDBGridMakeBookmark(I)
  2582.     End If
  2583.  
  2584. End Function
  2585.  
  2586. Private Function pvtDBGridIndexFromBookmark(Bookmark As Variant, ReadPriorRows As Boolean, MaxRow As Long) As Long
  2587.  
  2588.     Dim I As Long
  2589.  
  2590.     If IsNull(Bookmark) Then
  2591.         If ReadPriorRows Then
  2592.             pvtDBGridIndexFromBookmark = MaxRow
  2593.         Else
  2594.             pvtDBGridIndexFromBookmark = -1
  2595.         End If
  2596.     Else
  2597.         I = Val(Bookmark)
  2598.         
  2599.         If I < 0 Or I >= MaxRow Then
  2600.             I = -MaxRow
  2601.         End If
  2602.         
  2603.         pvtDBGridIndexFromBookmark = I
  2604.     End If
  2605.  
  2606. End Function
  2607.  
  2608. Private Function pvtDBGridMakeBookmark(Index As Long) As Variant
  2609.     pvtDBGridMakeBookmark = CStr(Index)
  2610. End Function
  2611.  
  2612.  
  2613. Private Function pvtDBGridObjectAtRowIndex(RowIndex As Long) As Variant
  2614. ' Returns the Object which occupies the row in the
  2615. '   DBGrid specified by RowIndex
  2616.  
  2617.     pvtDBGridObjectAtRowIndex = _
  2618.         pvtCollection.Item _
  2619.             (CollectionIndex _
  2620.                 (Key:=CStr(pvtDBGridBookmarkArray _
  2621.                     (2, RowIndex))))
  2622.  
  2623. End Function
  2624.  
  2625.  
  2626. Private Function pvtIsCollectionInstantiated() As Long
  2627. Attribute pvtIsCollectionInstantiated.VB_Description = "(Private) internal function"
  2628. ' Verify that the pvtCollection has been
  2629. '   instantiated
  2630.  
  2631.     If pvtCollection Is Nothing Then
  2632.         pvtErrorMessage TypeName(Me) & " cannot provide meaningfuly functionality because the collection has not been built."
  2633.         pvtIsCollectionInstantiated = False
  2634.         Exit Function
  2635.     End If
  2636.  
  2637.     pvtIsCollectionInstantiated = True
  2638. End Function
  2639.  
  2640. Private Function pvtIsRecordSetInitialized() As Long
  2641. Attribute pvtIsRecordSetInitialized.VB_Description = "(Private) internal function"
  2642. ' Verify that the RecordSet has been initialized
  2643.  
  2644.     If pvtRecordSet Is Nothing Then
  2645.         pvtErrorMessage TypeName(Me) & " cannot insert data into the database because the collection was never built."
  2646.         pvtIsRecordSetInitialized = False
  2647.         Exit Function
  2648.     End If
  2649.  
  2650.     pvtIsRecordSetInitialized = True
  2651. End Function
  2652.  
  2653. Private Function pvtIsSQLAccessable() As Long
  2654. Attribute pvtIsSQLAccessable.VB_Description = "(Private) internal function"
  2655. ' Determine whether or not the desired table data
  2656. '   can be derived, given the information provided
  2657.     
  2658.     If (pvtParent Is Nothing _
  2659.     And pvtWhereClause = "" _
  2660.     And pvtSQLStatement = "" _
  2661.     ) Then
  2662.         pvtErrorMessage TypeName(Me) & " cannot perform object instantiations without having been provided with either an SQL:=, a WhereClause:= or a Parent:= ."
  2663.         pvtIsSQLAccessable = False
  2664.         Exit Function
  2665.     End If
  2666.  
  2667.     pvtIsSQLAccessable = True
  2668. End Function
  2669.  
  2670.  
  2671. Public Function Collection() As Collection
  2672. Attribute Collection.VB_Description = "Returns the underlying VB Collection"
  2673. ' Returns the underlying Collection object
  2674.  
  2675.     Set Collection = pvtCollection
  2676. End Function
  2677.  
  2678. Private Function pvtConcatenateOrderByClause(Optional SQL As Variant, Optional OrderByClause As Variant) As String
  2679. ' Return either a null string or an OrderBy clause
  2680. '   including the leading "Order By"
  2681.  
  2682.     If OrderByClause <> "" Then
  2683.         pvtConcatenateOrderByClause = _
  2684.             " ORDER BY " & _
  2685.             OrderByClause
  2686.     Else
  2687.         pvtConcatenateOrderByClause = ""
  2688.     End If
  2689.  
  2690. End Function
  2691.  
  2692.  
  2693. Private Function pvtCreateSQLStatement() As String
  2694. Attribute pvtCreateSQLStatement.VB_Description = "(Private) internal function"
  2695. ' Evaluate the available information and create
  2696. '   an SQL Statement to access the desired rows
  2697.  
  2698. ' decide how to acquire an SQL Statement:
  2699. '   first try the SQL Statement variable
  2700.     If pvtSQLStatement = "" Then
  2701.             pvtSQLStatement = _
  2702.                 pvtBuildSQLStatementFromParent( _
  2703.                     Parent:=pvtParent)
  2704.     End If
  2705.  
  2706.     pvtCreateSQLStatement = pvtSQLStatement
  2707. End Function
  2708.  
  2709. Private Function pvtDBInsert(Optional Item As Variant) As Long
  2710. Attribute pvtDBInsert.VB_Description = "(Private) inserts the item from the associated table"
  2711. ' Insert Item into the table, then return
  2712. '   its ObjectID value
  2713.  
  2714.     Dim tempObjectErr As Long
  2715.     Dim tempBookmark As String
  2716.  
  2717.     On Local Error Resume Next
  2718.     
  2719.     If Not pvtIsRecordSetInitialized() Then
  2720.         pvtDBInsert = False
  2721.         Exit Function
  2722.     End If
  2723.     
  2724. ' prepare a new record area
  2725.     pvtRecordSet.AddNew
  2726.  
  2727. ' have the Item populate the RecordSet.
  2728. '   check for errors on that end
  2729.     Err = 0
  2730.     tempObjectErr = _
  2731.         Item.ObjectInitializeRecordSet(pvtRecordSet)
  2732.     If tempObjectErr <> 0 _
  2733.     Or Err <> 0 Then
  2734.         If Err = pvtReceiverDoesNotSupportThisMethod Or tempObjectErr = pvtReceiverDoesNotSupportThisMethod Then
  2735.             pvtErrorMessage "Class Module '" & TypeName(Item) & "' does not support the method 'InitializeRecordSet'." & vbCrLf & "Object cannot be supported by " & TypeName(Me) & " without this method."
  2736.         End If
  2737.         
  2738.         pvtDBInsert = 0
  2739.         Exit Function
  2740.     End If
  2741.  
  2742. ' execute the update
  2743.     pvtRecordSet.Update
  2744.  
  2745. ' Note: the following "If" line is commented because
  2746. '   it is possible for Err to be contanimated by the
  2747. '   application if it is using this RecordSet, say
  2748. '   attached to a DataControl with a Reposition
  2749. '   event coded.
  2750. ' return the ObjectID
  2751. '    If Err = 0 Then
  2752.         tempBookmark = pvtRecordSet.LastModified
  2753.         pvtRecordSet.Bookmark = tempBookmark
  2754. '    End If
  2755.     
  2756.     pvtDBInsert = pvtRecordSet("ObjectID")
  2757. End Function
  2758.  
  2759.  
  2760. Private Function pvtErrorMessage(Optional ErrorMessage As Variant) As Long
  2761. Attribute pvtErrorMessage.VB_Description = "(Private) internal function"
  2762.     pvtErrorMessage = _
  2763.         pvtVBOFObjectManager.DisplayErrorMessage _
  2764.             (ErrorMessage)
  2765. End Function
  2766.  
  2767.  
  2768. Public Property Get ObjectManager() As VBOFObjectManager
  2769. ' Return my reference to the VBOFObjectManager
  2770.     
  2771.     Set ObjectManager = pvtVBOFObjectManager
  2772. End Property
  2773.  
  2774.  
  2775. Private Function pvtDBSelect(Optional SQL As Variant) As RecordSet
  2776. Attribute pvtDBSelect.VB_Description = "(Private) selects the contained items from the associated table"
  2777. ' Process the SQL Select statement and return
  2778. '   a RecordSet
  2779.  
  2780. ' open a RecordSet containing the desired rows
  2781.     Set pvtDBSelect = _
  2782.         pvtDatabase. _
  2783.             OpenRecordset( _
  2784.                 SQL, _
  2785.                 dbOpenDynaset, pvtODBCPassThrough)
  2786.     
  2787.     pvtDBHasBeenReferenced = True
  2788. End Function
  2789.  
  2790. Private Function pvtDBUpdate(Optional Item As Variant) As VBOFCollection
  2791. Attribute pvtDBUpdate.VB_Description = "(Private) updates the item from the associated table"
  2792. ' Update the Item in the table
  2793.  
  2794.     On Local Error Resume Next
  2795.     
  2796.     If pvtRecordSet Is Nothing Then
  2797.         pvtErrorMessage TypeName(Me) & " cannot update data in the database because the collection was never built."
  2798.         Set pvtDBUpdate = Nothing
  2799.         Exit Function
  2800.     End If
  2801.     
  2802. ' prepare a new record area
  2803.     pvtRecordSet.Edit
  2804.  
  2805. ' have the Item populate the RecordSet
  2806.     Item.ObjectInitializeRecordSet (pvtRecordSet)
  2807.     If Err = pvtReceiverDoesNotSupportThisMethod Then
  2808.         pvtErrorMessage "Class Module '" & TypeName(Item) & "' does not support the method 'InitializeRecordSet'." & vbCrLf & "Object cannot be supported by " & TypeName(Me) & " without this method."
  2809.     End If
  2810.     
  2811. ' execute the update
  2812.     pvtRecordSet.Update
  2813.  
  2814. ' return the colection
  2815.     Set pvtDBUpdate = Me
  2816. End Function
  2817.  
  2818. Private Function pvtDBDelete() As Long
  2819. Attribute pvtDBDelete.VB_Description = "(Private) deletes the item from the associated table"
  2820. ' Delete the current row of the RecordSet
  2821.  
  2822.     On Local Error Resume Next
  2823.     
  2824. ' bullet-proofing
  2825.     If pvtRecordSet Is Nothing Then
  2826.         pvtErrorMessage TypeName(Me) & " cannot delete data in the database because the collection was never built."
  2827.         pvtDBDelete = False
  2828.         Exit Function
  2829.     End If
  2830.         
  2831. ' delete the record
  2832.     Err = 0
  2833.     pvtRecordSet.Delete
  2834.  
  2835.     If Err = 0 Then
  2836.         pvtDBDelete = True
  2837.     Else
  2838.         pvtDBDelete = False
  2839.     End If
  2840. End Function
  2841.  
  2842.  
  2843. Private Function pvtInstantiateObjectsFromRecordSet(Optional RecordSet As Variant, Optional Collection) As Collection
  2844. ' Return a Collection of objects which have been
  2845. '   instantiated from data found in RecordSet
  2846.     
  2847.     Dim tempRow As Object
  2848.     Dim newChildObject As Object
  2849.     Dim tempIndex As Long
  2850.     Dim tempCollection As New Collection
  2851.  
  2852.     On Local Error Resume Next
  2853.  
  2854. ' clear the pvtDBGridBookmarkArray
  2855.     pvtDBGridBookmarkArrayClear
  2856.     
  2857. ' process the RecordSet
  2858.     While Not RecordSet.EOF
  2859.     
  2860. ' determine whether or not the retrieved row
  2861. '   has an instantiated object already in the
  2862. '   VBOFCollection
  2863.         tempIndex = _
  2864.             CollectionIndex( _
  2865.                 Item:=CStr(RecordSet("ObjectID")))
  2866.         If tempIndex > 0 Then
  2867.             Set newChildObject = _
  2868.                 pvtCollection(tempIndex)
  2869.         
  2870. ' else, must instantiate a new object of the class
  2871.         Else
  2872.         
  2873. ' have the Sample Object return an instantiated
  2874. '   copy of itself
  2875.             Set newChildObject = _
  2876.                 ObjectManager. _
  2877.                     pvtInstantiateNewObjectFromSample _
  2878.                         (Sample:=pvtSample)
  2879.             If newChildObject Is Nothing Then
  2880.                 GoTo pvtInstantiateObjectsFromRecordSet_Error
  2881.             End If
  2882.         End If
  2883.  
  2884. ' have the new instantiated object copy populate
  2885. '   itself from this RecordSet row
  2886.         Set newChildObject = _
  2887.             ObjectManager. _
  2888.                 pvtObjectInitializeFromRecordSet( _
  2889.                     Object:=newChildObject, _
  2890.                     RecordSet:=RecordSet)
  2891.         If newChildObject Is Nothing Then
  2892.             GoTo pvtInstantiateObjectsFromRecordSet_Exit
  2893.         End If
  2894.         
  2895. ' add the object to the collection
  2896. '   (if it is unique)
  2897.         pvtAddUniqueItemToCollection _
  2898.             Item:=newChildObject, _
  2899.             Parent:=Me, _
  2900.             Collection:=tempCollection
  2901.         
  2902.         RecordSet.MoveNext
  2903.     Wend
  2904.         
  2905.     GoTo pvtInstantiateObjectsFromRecordSet_Exit
  2906.  
  2907. pvtInstantiateObjectsFromRecordSet_Error:
  2908.     
  2909. pvtInstantiateObjectsFromRecordSet_Exit:
  2910.     Set pvtInstantiateObjectsFromRecordSet = _
  2911.         tempCollection
  2912.     Set tempRow = Nothing
  2913.     Set newChildObject = Nothing
  2914. End Function
  2915. Private Function pvtIsDatabaseSpecified() As Integer
  2916. Attribute pvtIsDatabaseSpecified.VB_Description = "(Private) internal function"
  2917. ' Determine whether or not the database has been
  2918. '   specified
  2919.  
  2920.     If pvtDatabase Is Nothing Then
  2921.         pvtErrorMessage TypeName(Me) & " cannot function without having been provided the name of the database.  Use the 'Database:=' parameter of the pvtPopulateFromDatabase method to specify the database."
  2922.         pvtIsDatabaseSpecified = False
  2923.         Exit Function
  2924.     End If
  2925.  
  2926.     pvtIsDatabaseSpecified = True
  2927. End Function
  2928.  
  2929. Private Function pvtSetParent(Optional Parent As Variant, Optional MethodName As Variant) As Boolean
  2930.     
  2931.     On Local Error Resume Next
  2932.     
  2933.     pvtSetParent = True
  2934.     
  2935.     If IsMissing(Parent) Then
  2936.         If pvtParent Is Nothing Then
  2937.             pvtErrorMessage TypeName(Me) & " cannot process the '." & MethodName & "' method for this object because the 'Parent:=' parameter is missing and no preceeding method has established a default object."
  2938.             pvtSetParent = False
  2939.         End If
  2940.     ElseIf Not Parent Is Nothing Then
  2941.         Set pvtParent = Parent
  2942.     End If
  2943.  
  2944. End Function
  2945.  
  2946. Private Function pvtSetSample(Optional Sample As Variant, Optional MethodName As Variant) As Boolean
  2947.     
  2948.     On Local Error Resume Next
  2949.     
  2950.     pvtSetSample = True
  2951.     
  2952.     If IsMissing(Sample) Then
  2953.         If pvtSample Is Nothing Then
  2954.             pvtErrorMessage TypeName(Me) & " cannot process the '." & MethodName & "' method for this object because the 'Sample' parameter is missing and no preceeding method has established a default."
  2955.             pvtSetSample = False
  2956.         End If
  2957.     End If
  2958.  
  2959. End Function
  2960.  
  2961.  
  2962. Private Sub pvtReceiveGeneralParameters(Optional Database As Variant, Optional Sample As Variant, Optional Parent As Variant, Optional WhereClause As Variant, Optional SQL As Variant, Optional OrderByClause As Variant, Optional CollectionEmulationMode As Variant, Optional ANSISQL As Variant, Optional ODBCPassThrough As Variant)
  2963. Attribute pvtReceiveGeneralParameters.VB_Description = "(Private) internal function"
  2964. ' Receive user-defined parameters
  2965.  
  2966.     If Not IsMissing(Database) Then
  2967.         Set pvtDatabase = Database
  2968.         pvtCollectionEmulationMode = False
  2969.     End If
  2970.     
  2971.     If Not IsMissing(Sample) Then
  2972.         Set pvtSample = Sample
  2973.     End If
  2974.     
  2975.     If Not IsMissing(Parent) Then
  2976.         
  2977.         Set pvtParent = Parent
  2978.     End If
  2979.     
  2980.     If Not IsMissing(WhereClause) Then
  2981.         pvtWhereClause = WhereClause
  2982.         pvtCollectionEmulationMode = False
  2983.     End If
  2984.     
  2985.     If Not IsMissing(SQL) Then
  2986.         pvtSQLStatement = SQL
  2987.         pvtCollectionEmulationMode = False
  2988.         pvtSQLStatementProvidedByUser = True
  2989.     End If
  2990.     
  2991.     If Not IsMissing(OrderByClause) Then
  2992.         pvtOrderByClause = OrderByClause
  2993.         pvtCollectionEmulationMode = False
  2994.     End If
  2995.  
  2996.     If Not IsMissing(CollectionEmulationMode) Then
  2997.         pvtCollectionEmulationMode = CollectionEmulationMode
  2998.     End If
  2999.  
  3000.     If Not IsMissing(ANSISQL) Then
  3001.         pvtANSISQL = ANSISQL
  3002.     End If
  3003.     
  3004.     If Not IsMissing(ODBCPassThrough) Then
  3005.         If ODBCPassThrough Then
  3006.             pvtODBCPassThrough = dbSQLPassThrough
  3007.         Else
  3008.             pvtODBCPassThrough = 0
  3009.         End If
  3010.     End If
  3011. End Sub
  3012.  
  3013. Public Property Get pvtRecordSetAbsolutePosition() As Long
  3014. ' Gets the RecordSet's AbsolutePosition
  3015. '   property
  3016.  
  3017.     pvtRecordSetAbsolutePosition = _
  3018.         pvtRecordSet.AbsolutePosition
  3019. End Property
  3020.  
  3021. Public Property Let pvtRecordSetAbsolutePosition(RecordNumber As Long)
  3022. ' Sets the RecordSet's AbsolutePosition
  3023. '   property
  3024.  
  3025.     pvtRecordSet.AbsolutePosition = _
  3026.         RecordNumber
  3027. End Property
  3028.  
  3029. Public Function pvtRecordSetMoveFirst() As Variant
  3030. ' Moves the underlying RecordSet to the first record
  3031. '   and returns the object for that row
  3032.  
  3033.     Dim tempObject As Object
  3034.  
  3035.     On Local Error Resume Next
  3036.  
  3037.     pvtRecordSet.MoveFirst
  3038.  
  3039.     If pvtRecordSet.AbsolutePosition >= 0 Then
  3040.         Set pvtRecordSetMoveFirst = _
  3041.             Item(pvtRecordSet.AbsolutePosition + 1)
  3042.     Else
  3043.         Set pvtRecordSetMoveFirst = Nothing
  3044.     End If
  3045. End Function
  3046.  
  3047. Public Function pvtRecordSetFindFirst(Optional SearchCriteria As Variant) As Variant
  3048. ' Searches the underlying RecordSet for the first
  3049. '   record meeting the specified criteria
  3050. '   and returns the object for that row
  3051.  
  3052.     Dim tempObject As Object
  3053.  
  3054.     On Local Error Resume Next
  3055.  
  3056.     pvtRecordSet.FindFirst SearchCriteria
  3057.  
  3058.     If pvtRecordSet.AbsolutePosition >= 0 Then
  3059.         Set pvtRecordSetFindFirst = _
  3060.             Item(pvtRecordSet.AbsolutePosition + 1)
  3061.     Else
  3062.         Set pvtRecordSetFindFirst = Nothing
  3063.     End If
  3064. End Function
  3065.  
  3066. Public Function pvtRecordSetFindNext(Optional SearchCriteria As Variant) As Variant
  3067. ' Searches the underlying RecordSet for the next
  3068. '   record meeting the specified criteria
  3069. '   and returns the object for that row
  3070.  
  3071.     Dim tempObject As Object
  3072.  
  3073.     On Local Error Resume Next
  3074.  
  3075.     pvtRecordSet.FindNext SearchCriteria
  3076.  
  3077.     If pvtRecordSet.AbsolutePosition >= 0 Then
  3078.         Set pvtRecordSetFindNext = _
  3079.             Item(pvtRecordSet.AbsolutePosition + 1)
  3080.     Else
  3081.         Set pvtRecordSetFindNext = Nothing
  3082.     End If
  3083. End Function
  3084.  
  3085. Public Function pvtRecordSetFindPrevious(Optional SearchCriteria As Variant) As Variant
  3086. ' Searches the underlying RecordSet for the previous
  3087. '   record meeting the specified criteria
  3088. '   and returns the object for that row
  3089.  
  3090.     Dim tempObject As Object
  3091.  
  3092.     On Local Error Resume Next
  3093.  
  3094.     pvtRecordSet.FindPrevious SearchCriteria
  3095.  
  3096.     If pvtRecordSet.AbsolutePosition >= 0 Then
  3097.         Set pvtRecordSetFindPrevious = _
  3098.             Item(pvtRecordSet.AbsolutePosition + 1)
  3099.     Else
  3100.         Set pvtRecordSetFindPrevious = Nothing
  3101.     End If
  3102. End Function
  3103.  
  3104.  
  3105. Public Function pvtRecordSetFindLast(Optional SearchCriteria As Variant) As Variant
  3106. ' Searches the underlying RecordSet for the last
  3107. '   record meeting the specified criteria
  3108. '   and returns the object for that row
  3109.  
  3110.     Dim tempObject As Object
  3111.  
  3112.     On Local Error Resume Next
  3113.  
  3114.     pvtRecordSet.FindLast SearchCriteria
  3115.  
  3116.     If pvtRecordSet.AbsolutePosition >= 0 Then
  3117.         Set pvtRecordSetFindLast = _
  3118.             Item(pvtRecordSet.AbsolutePosition + 1)
  3119.     Else
  3120.         Set pvtRecordSetFindLast = Nothing
  3121.     End If
  3122. End Function
  3123.  
  3124.  
  3125.  
  3126. Public Function pvtRecordSetMoveLast() As Variant
  3127. ' Moves the underlying RecordSet to the last record
  3128. '   and returns the object for that row
  3129.  
  3130.     Dim tempObject As Object
  3131.  
  3132.     On Local Error Resume Next
  3133.  
  3134.     pvtRecordSet.MoveLast
  3135.  
  3136.     pvtRecordSetMoveLast = True
  3137.     
  3138.     If pvtRecordSet.AbsolutePosition >= 0 Then
  3139.         Set pvtRecordSetMoveLast = _
  3140.             Item(pvtRecordSet.AbsolutePosition + 1)
  3141.     Else
  3142.         Set pvtRecordSetMoveLast = Nothing
  3143.     End If
  3144. End Function
  3145.  
  3146. Public Function pvtRecordSetMoveToRecordNumber(Optional RecordNumber As Variant) As Variant
  3147. ' Moves the underlying RecordSet to the specified
  3148. '   record (by number) and returns the object for
  3149. '   that row
  3150.  
  3151.     Dim tempObject As Object
  3152.  
  3153.     On Local Error Resume Next
  3154.  
  3155. ' bullet-proofing
  3156.     If pvtRecordSet.RecordCount < RecordNumber Then
  3157.         Set pvtRecordSetMoveToRecordNumber = Nothing
  3158.         Exit Function
  3159.     End If
  3160.  
  3161.     pvtRecordSet.AbsolutePosition = _
  3162.         RecordNumber
  3163.     
  3164.     Set pvtRecordSetMoveToRecordNumber = _
  3165.         Item(pvtRecordSet.AbsolutePosition) ' ObjectID:=CStr(pvtRecordSet("ObjectID")))
  3166. End Function
  3167.  
  3168. Public Function pvtRecordSetPositionToItem(Optional Item As Variant) As Variant
  3169. ' Positions the underlying RecordSet to the
  3170. '   specifed Item and returns the Item
  3171.  
  3172.     Set pvtRecordSetPositionToItem = _
  3173.         pvtPositionRecordSetToItem _
  3174.             (Item:=Item)
  3175. End Function
  3176.  
  3177.  
  3178. Public Function pvtRecordSetRefresh() As RecordSet
  3179. ' Pass thru to pvtRefreshRecordSet()
  3180.     
  3181.     Set pvtRecordSetRefresh = _
  3182.         pvtRefreshRecordSet()
  3183. End Function
  3184.  
  3185. Public Function pvtRecordSetBOF() As Boolean
  3186. ' Returns a boolean, based on whether or not the
  3187. ' underlying RecordSet is positioned at BOF
  3188.     
  3189.     On Local Error Resume Next
  3190.     
  3191.     pvtRecordSetBOF = _
  3192.         pvtRecordSet.BOF
  3193. End Function
  3194.  
  3195.  
  3196. Public Function pvtRecordSetRecordCount() As Long
  3197. ' Returns the RecordCount property of the
  3198. ' underlying RecordSet
  3199.     
  3200.     On Local Error Resume Next
  3201.     
  3202.     pvtRecordSetRecordCount = _
  3203.         pvtRecordSet.RecordCount
  3204. End Function
  3205.  
  3206. Public Function pvtRecordSetEOF() As Boolean
  3207. ' Returns a boolean, based on whether or not the
  3208. '   underlying RecordSet is positioned at EOF
  3209.     
  3210.     On Local Error Resume Next
  3211.     
  3212.     pvtRecordSetEOF = _
  3213.         pvtRecordSet.EOF
  3214. End Function
  3215.  
  3216.  
  3217. Public Function pvtRefreshRecordSet() As RecordSet
  3218. Attribute pvtRefreshRecordSet.VB_Description = "Refreshes the internally managed RecordSet which equates to the rows of the table which were used to instantiate the contained items.  Returns the RecordSet"
  3219. ' Return the refreshed RecordSet after having refreshed its
  3220. '   contents by again using the same SQL-oriented
  3221. '   information used previously to generate the current
  3222. '   VBOFCollection state.
  3223. ' Note: users of the method "pvtPopulateFromRecordSet"
  3224. '   should not use this method
  3225.  
  3226.     On Local Error Resume Next
  3227.  
  3228.     If pvtRecordSetProvidedByUser Then
  3229.         pvtErrorMessage TypeName(Me) & " cannot process the '.pvtRefreshRecordSet' method because the RecordSet used to instantiate the objects was provided by the user via the '.pvtPopulateFromRecordSet' method."
  3230.         Set Refresh = Me
  3231.     End If
  3232.  
  3233.     Refresh
  3234.     
  3235.     Set pvtRefreshRecordSet = pvtRecordSet
  3236. End Function
  3237.  
  3238.  
  3239. Public Sub SetDatabaseParameters(Optional Database As Variant, Optional Sample As Variant, Optional Parent As Variant, Optional WhereClause As Variant, Optional SQL As Variant, Optional OrderByClause As Variant, Optional CollectionEmulationMode As Variant, Optional ANSISQL As Variant, Optional ODBCPassThrough As Variant)
  3240. Attribute SetDatabaseParameters.VB_Description = "(Private) Allows the user to set all of the database-related parameters in a single statement"
  3241. ' Receive any database parameters the application
  3242. '   program wishes to set en masse.  As an
  3243. '   alternative, the application can provide
  3244. '   certain parameters for certain methods,
  3245. '   such as the .pvtPopulateFromRecordSet
  3246. '   and .pvtPopulateFromDatabase methods
  3247.  
  3248.     pvtReceiveGeneralParameters _
  3249.         Database:=Database, _
  3250.         Sample:=Sample, _
  3251.         Parent:=Parent, _
  3252.         WhereClause:=WhereClause, _
  3253.         OrderByClause:=OrderByClause, _
  3254.         SQL:=SQL, _
  3255.         CollectionEmulationMode:=CollectionEmulationMode, _
  3256.         ANSISQL:=ANSISQL, _
  3257.         ODBCPassThrough:=ODBCPassThrough
  3258.  
  3259. End Sub
  3260.  
  3261. Private Function pvtPopulateFromRecordSet(Optional RecordSet As Variant, Optional Database As Variant, Optional Sample As Variant, Optional Parent As Variant, Optional WhereClause As Variant, Optional SQL As Variant, Optional OrderByClause As Variant, Optional ANSISQL As Variant, Optional ODBCPassThrough As Variant) As VBOFCollection
  3262. Attribute pvtPopulateFromRecordSet.VB_Description = "Sets the internally managed RecordSet"
  3263. ' Sets a VBOFCollection object which has been
  3264. '   instantiated as a collection of objects
  3265. '   represented by the contents of RecordSet
  3266. ' Note: use of this method requires that the
  3267. '   caller maintain all of the necessary object
  3268. '   containment information, since VBOFCollection
  3269. '   is unaware of the techniques used to derive the
  3270. '   contents of RecordSet
  3271. '
  3272. ' Parameter Description:
  3273. '       see VBOFObjetManager.ManageCollection
  3274.     
  3275.     On Local Error Resume Next
  3276.  
  3277. ' bullet-proofing
  3278.     If IsMissing(RecordSet) Then
  3279.         pvtErrorMessage TypeName(Me) & " cannot process the '.pvtPopulateFromRecordSet' method because the 'RecordSet:=' parameter is mssing."
  3280.         Set pvtPopulateFromRecordSet = Nothing
  3281.     End If
  3282.  
  3283. ' test Sample for Database-readiness
  3284.     If Not IsMissing(Sample) Then
  3285.         If (Sample.ObjectDataSource = "" Or Err = 438) Then
  3286.             pvtCollectionEmulationMode = True
  3287.         End If
  3288.     End If
  3289.  
  3290.     pvtReceiveGeneralParameters _
  3291.         Database:=Database, _
  3292.         Sample:=Sample, _
  3293.         Parent:=Parent, _
  3294.         WhereClause:=WhereClause, _
  3295.         OrderByClause:=OrderByClause, _
  3296.         ANSISQL:=ANSISQL, _
  3297.         ODBCPassThrough:=ODBCPassThrough, _
  3298.         SQL:=SQL
  3299.  
  3300. ' reference the RecordSet containing the desired rows
  3301.     Set pvtRecordSet = RecordSet
  3302.  
  3303. ' create the objects from the contents of the RecordSet
  3304.     Set pvtCollection = _
  3305.         pvtInstantiateObjectsFromRecordSet( _
  3306.             RecordSet:=pvtRecordSet, _
  3307.             Collection:=pvtCollection)
  3308.     
  3309. #If NoDebugMode = False Then
  3310.     If pvtVBOFObjectManager.DebugMode Then
  3311.         pvtVBOFObjectManager.DisplayDebugMessage _
  3312.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has instantiated a collection of objects from a user-defined RecordSet.  " & _
  3313.             "Object count=" & pvtCollection.Count
  3314.     End If
  3315. #End If
  3316.  
  3317. ' trigger the "PopulatedFromRecordSet" event for Me
  3318. #If NoEventMgr = False Then
  3319.     TriggerCollectionEvent _
  3320.         Event:="PopulatedFromRecordSet"
  3321. #End If
  3322.     
  3323.     Set pvtPopulateFromRecordSet = Me
  3324. End Function
  3325.  
  3326. Public Function RecordSet() As RecordSet
  3327. Attribute RecordSet.VB_Description = "Returns the underlying RecordSet object"
  3328. ' Returns a DataControl-ready RecordSet object
  3329. '   which pertains to the collection of objects
  3330. '   instantiated and contained within this
  3331. '   VBOFCollection
  3332.     
  3333.     If pvtCollectionEmulationMode Then
  3334.         Set RecordSet = Nothing
  3335.         Exit Function
  3336.     End If
  3337.     
  3338.     Set RecordSet = pvtRecordSet
  3339. End Function
  3340.  
  3341. Public Function SQLStatement() As String
  3342. Attribute SQLStatement.VB_Description = "Returns the most recently used SQL statement"
  3343.     SQLStatement = pvtSQLStatement
  3344. End Function
  3345.  
  3346. Public Function Refresh() As VBOFCollection
  3347. Attribute Refresh.VB_Description = "Refreshes the internally managed RecordSet which equates to the rows of the table which were used to instantiate the contained items.  Returns the refreshed VBOFCollection"
  3348. ' Return a refreshed VBOFCollection, using again
  3349. '   the same SQL-oriented information used previously
  3350. '   to generate the current VBOFCollection state.
  3351. ' Note: users of the method "pvtPopulateFromRecordSet"
  3352. '   should not use this method
  3353.  
  3354.     On Local Error Resume Next
  3355.  
  3356. ' bullet-proofing
  3357.     If pvtRecordSetProvidedByUser Then
  3358.         pvtErrorMessage TypeName(Me) & " cannot process the '.Refresh' method because the RecordSet used to instantiate the objects was provided by the user via the '.pvtPopulateFromRecordSet' method."
  3359.         Set Refresh = Me
  3360.         GoTo Refresh_Exit
  3361.     End If
  3362.  
  3363. ' refresh the Collection
  3364.     If pvtCollectionEmulationMode Then
  3365.         Set Refresh = Me
  3366.     Else
  3367.         Set Refresh = _
  3368.             pvtPopulateFromDatabase()
  3369.     End If
  3370.     
  3371. #If NoDebugMode = False Then
  3372.     If pvtVBOFObjectManager.DebugMode Then
  3373.         pvtVBOFObjectManager.DisplayDebugMessage _
  3374.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has refreshed its collection of objects (.Refresh).  " & _
  3375.             "Object count=" & pvtCollection.Count
  3376.     End If
  3377. #End If
  3378.  
  3379. Refresh_Exit:
  3380. ' trigger the "Refreshed" event for Me
  3381. #If NoEventMgr = False Then
  3382.     TriggerCollectionEvent _
  3383.         Event:="Refreshed"
  3384. #End If
  3385.  
  3386.     Exit Function
  3387. End Function
  3388.  
  3389. Public Function Remove(Optional Item As Variant, Optional Key As Variant, Optional NoDelete As Variant, Optional CleanUpMode As Variant, Optional CollectionEventNoDelete As Variant) As VBOFCollection
  3390. Attribute Remove.VB_Description = "Removes the item from the VBOFCollection"
  3391. ' Remove the Item from the VBOFCollection and
  3392. '   return the VBOFCollection
  3393. ' Note: if a Table is supporting the Collection,
  3394. '   then the VBOF automatic containment link to
  3395. '   the contained object (Me.Parent) is also severed
  3396. '   (unless CleanUpMode:=True).
  3397. '   See also, the method "pvtEmptyCollection"
  3398.  
  3399.     Dim tempCountOfParentLinksToItem As Long
  3400.     Dim tempSuppressDelete As Boolean
  3401.     Dim tempPvtDeleteExecuted As Boolean
  3402.     Dim tempCleanUpMode As Boolean
  3403.     Dim tempCollectionEventNoDelete As Boolean
  3404.  
  3405.     On Local Error Resume Next
  3406.  
  3407. ' bullet-proofing
  3408.     If IsMissing(Item) Then
  3409.         Remove = Me
  3410.         Exit Function
  3411.     End If
  3412.     tempSuppressDelete = False
  3413.     If Not IsMissing(NoDelete) Then
  3414.         tempSuppressDelete = NoDelete
  3415.     End If
  3416.     tempCleanUpMode = False
  3417.     If Not IsMissing(CleanUpMode) Then
  3418.         tempCleanUpMode = CleanUpMode
  3419.     End If
  3420.     tempCollectionEventNoDelete = False
  3421.     If Not IsMissing(CollectionEventNoDelete) Then
  3422.         tempCollectionEventNoDelete = CollectionEventNoDelete
  3423.     End If
  3424.  
  3425. ' sever the link from pvtParent to Item
  3426.     If Not pvtCollectionEmulationMode _
  3427.     And Not tempSuppressDelete Then
  3428.         pvtDeleteParentLinksToItem _
  3429.             Child:=Item, _
  3430.             Parent:=pvtParent
  3431.     End If
  3432.  
  3433. ' remove the reference from the
  3434. '   pvtDBGridBookmarkArray
  3435.     pvtDBGridBookmarkArrayDeleteRowIndex ( _
  3436.         pvtDBGridRowIndexAtObjectID _
  3437.             (CStr(Item.ObjectID)))
  3438.         
  3439. ' remove Item from the Collection
  3440.     pvtCollection.Remove _
  3441.         CollectionIndex(Item)
  3442.  
  3443. ' trigger the "RemovedItem" event to other Collections
  3444. #If NoEventMgr = False Then
  3445.     If Not CleanUpMode Then
  3446.         TriggerCollectionEvent _
  3447.             Object:=Item, _
  3448.             Event:="RemovedItem", _
  3449.             NoDelete:=tempCollectionEventNoDelete
  3450.     End If
  3451. #End If
  3452.     
  3453. ' if not operating in Collection-emulation mode
  3454.     If Not pvtCollectionEmulationMode _
  3455.     And Not tempCleanUpMode _
  3456.     Then
  3457.  
  3458. ' check for orphan and other conditions necessary before
  3459. '   actually removing an Item from the database
  3460. '   (if not operating in NoDelete mode,
  3461. '   and if the AutoDeleteOrphans option is enabled,
  3462. '   and if the Item actually appears in the
  3463. '   RecordSet)
  3464.         If Not tempSuppressDelete _
  3465.         And Me.AutoDeleteOrphans _
  3466.         And Not pvtPositionRecordSetToItem _
  3467.                 (Item:=Item) Is Nothing _
  3468.         And pvtIsAnOrphan _
  3469.                 (Item:=Item) _
  3470.         Then
  3471.  
  3472. ' delete Item from the database
  3473. '   and free the Item
  3474.             pvtDBDelete
  3475.         
  3476. ' trigger the "RemovedItem" event for the new object
  3477. '   to any other listeners
  3478. #If NoEventMgr = False Then
  3479.             If Not CleanUpMode Then
  3480.                 TriggerObjectEvent _
  3481.                     Object:=Item, _
  3482.                     Event:="RemovedItem"
  3483.             End If
  3484. #End If
  3485.  
  3486. ' else, just Refresh the current RecordSet to
  3487. '   reflect the detached Item
  3488.         ElseIf Not pvtRecordSetProvidedByUser Then
  3489.             Refresh
  3490.         End If
  3491.     End If
  3492.     
  3493. #If NoDebugMode = False Then
  3494.     If pvtVBOFObjectManager.DebugMode Then
  3495.         pvtVBOFObjectManager.DisplayDebugMessage _
  3496.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has removed an object from the collection.  ObjectType=" & _
  3497.             TypeName(Item) & _
  3498.             ", ObjectID=" & _
  3499.             Item.ObjectID
  3500.     End If
  3501. #End If
  3502.  
  3503.     Set Remove = Me
  3504. End Function
  3505.  
  3506. Private Function pvtCountOfParentLinksToItem(Optional Parent As Variant, Optional Child As Variant) As Long
  3507. ' Return the number of Parent links exist for
  3508. '   the specified Child object
  3509.  
  3510.     Dim SQLStatement As String
  3511.     Dim tempRecordSet As RecordSet
  3512.  
  3513.     On Local Error Resume Next
  3514.  
  3515. ' bullet-proofing
  3516.     If IsMissing(Parent) _
  3517.     Or IsMissing(Child) _
  3518.     Or pvtCollectionEmulationMode Then
  3519.         pvtCountOfParentLinksToItem = -1
  3520.         Exit Function
  3521.     End If
  3522.     
  3523.     Err = 0
  3524.  
  3525. ' build the SQL statement to perform the Count
  3526.     SQLStatement = _
  3527.         "SELECT COUNT(*) FROM " & ObjectDataSource() & " " & _
  3528.         "WHERE ToObjectType = '" & _
  3529.         TypeName(Child) & "' AND ToObjectID = " & _
  3530.         Child.ObjectID
  3531.         
  3532. ' check for non-existent Object
  3533.     If Err = 91 Then
  3534.         pvtCountOfParentLinksToItem = 0
  3535.         Exit Function
  3536.     End If
  3537.     
  3538.     Set tempRecordSet = _
  3539.         pvtDatabase. _
  3540.             OpenRecordset( _
  3541.                 SQLStatement, _
  3542.                 dbOpenDynaset + pvtODBCPassThrough)
  3543.  
  3544.     If Err <> 0 And Err <> 91 Then
  3545.         pvtErrorMessage _
  3546.             TypeName(Me) & " received a database error while attempting to count the object containment links (Select Count(*))."
  3547.         pvtCountOfParentLinksToItem = 0
  3548.     Else
  3549.         pvtCountOfParentLinksToItem = _
  3550.             tempRecordSet(0)
  3551.     End If
  3552.  
  3553.     Set tempRecordSet = Nothing
  3554. End Function
  3555.  
  3556. Private Function pvtDeleteParentLinksToItem(Optional Parent As Variant, Optional Child As Variant) As Long
  3557. ' Remove the link between the Parent and Child
  3558.     
  3559.     Dim SQLStatement As String
  3560.     
  3561.     On Local Error Resume Next
  3562.  
  3563.     If pvtCollectionEmulationMode Then
  3564.         pvtDeleteParentLinksToItem = True
  3565.         Exit Function
  3566.     End If
  3567.     
  3568.     Err = 0
  3569.  
  3570. ' delete the row from the VBObjectFrameworkObjectLinks table
  3571.     SQLStatement = _
  3572.         "DELETE FROM " & ObjectDataSource() & " WHERE FromObjectType = '" & _
  3573.         TypeName(Parent) & "' AND FromObjectID = " & _
  3574.         Parent.ObjectID & " AND ToObjectType = '" & _
  3575.         TypeName(Child) & "' AND ToObjectID = " & _
  3576.         Child.ObjectID
  3577.     
  3578. ' check for illegal Object
  3579.     If Err = 91 Then
  3580.         pvtDeleteParentLinksToItem = False
  3581.         Exit Function
  3582.     End If
  3583.     
  3584.     pvtDatabase.Execute SQLStatement, pvtODBCPassThrough
  3585.     If Err <> 0 And Err <> 3078 And Err <> 91 Then
  3586.         pvtErrorMessage TypeName(Me) & " received a database error while attempting to remove an object containment link (Delete)."
  3587.         pvtDeleteParentLinksToItem = False
  3588.         Exit Function
  3589.     End If
  3590.         
  3591.     pvtDeleteParentLinksToItem = True
  3592. End Function
  3593.  
  3594. Public Function Replace(Optional Item As Variant, Optional ReplaceWith As Variant) As VBOFCollection
  3595. Attribute Replace.VB_Description = "Replaces the item with the specified ReplaceWith item in the collection and in the associated Data Source"
  3596. ' Replace the specified Item with the ReplaceWith
  3597. '   Item, then return the VBOFCollection
  3598.     
  3599.     Dim ItemIndex As Long
  3600.     
  3601.     On Local Error Resume Next
  3602.  
  3603. ' bullet-proofing
  3604.     If IsMissing(Item) _
  3605.     Or IsMissing(ReplaceWith) Then
  3606.         Set Replace = Me
  3607.         GoTo Replace_Exit
  3608.     End If
  3609.     
  3610. ' there are two ways to handle a Replace:
  3611. '   1) replace the object in-place
  3612. '       (non Collection-emulation mode, only),
  3613. '   2) replace the object with another
  3614. '
  3615. ' process the replacement in-place:
  3616.     If Item.ObjectID = ReplaceWith.ObjectID _
  3617.     And Not pvtCollectionEmulationMode Then
  3618.         
  3619. ' position to the correct record in the RecordSet.
  3620. '   Note:  with non-DataControl uses of VBOFCollection,
  3621. '   it is possible for the correlation to be lost
  3622. '   between the current record of the RecordSet and
  3623. '   the user-selected object.
  3624. ' position the RecordSet to the Item
  3625.         If pvtPositionRecordSetToItem(Item:=Item) _
  3626.             Is Nothing _
  3627.         Then
  3628.             Set Replace = Me
  3629.             GoTo Replace_Exit
  3630.         End If
  3631.         
  3632. ' initiate the RecordSet.Edit
  3633.         pvtRecordSet.Edit
  3634.         
  3635. ' have ReplaceWith initialize the RecordSet
  3636.         ReplaceWith. _
  3637.             ObjectInitializeRecordSet _
  3638.                 pvtRecordSet
  3639.         If Err = pvtReceiverDoesNotSupportThisMethod Then
  3640.             pvtErrorMessage "Class Module '" & TypeName(ReplaceWith) & "' does not support the method 'InitializeRecordSet'." & vbCrLf & "Object cannot be supported by " & TypeName(Me) & " without this method."
  3641.         End If
  3642.         
  3643. ' post the updates to the database
  3644.         pvtRecordSet.Update
  3645.         
  3646. ' execute Me.Refresh
  3647.         Refresh
  3648.         
  3649.         Set Replace = Me
  3650.         GoTo Replace_Exit
  3651.     End If
  3652.     
  3653. ' else, Item must be removed and replaced with ReplaceWith.
  3654. ' save the position of Item in the Collection
  3655.     ItemIndex = CollectionIndex(Item)
  3656.  
  3657. ' remove Item from the RecordSet and the Collection
  3658.     Remove _
  3659.         Item:=Item, _
  3660.         Key:=CStr(Item.ObjectID), _
  3661.         NoDelete:=False, _
  3662.         CollectionEventNoDelete:=True
  3663.  
  3664. ' free Item
  3665.     Set Item = Nothing
  3666.  
  3667. ' add the ReplaceWith item
  3668.     If ItemIndex > 0 Then
  3669.         Add _
  3670.             Item:=ReplaceWith, _
  3671.             Parent:=pvtParent, _
  3672.             After:=(ItemIndex - 1)
  3673.     Else
  3674.         Add _
  3675.             Item:=ReplaceWith, _
  3676.             Parent:=pvtParent
  3677.     End If
  3678.     
  3679. #If NoDebugMode = False Then
  3680.     If pvtVBOFObjectManager.DebugMode Then
  3681.         pvtVBOFObjectManager.DisplayDebugMessage _
  3682.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has replaces an object in the collection.  Original ObjectType=" & _
  3683.             TypeName(Item) & _
  3684.             ", ObjectID=" & _
  3685.             Item.ObjectID & " replaced with ObjectType=" & _
  3686.             TypeName(ReplaceWith) & _
  3687.             ", ObjectID=" & _
  3688.             ReplaceWith.ObjectID
  3689.     End If
  3690. #End If
  3691.  
  3692. Replace_Exit:
  3693. ' trigger the "Replaced" event for Me
  3694. #If NoEventMgr = False Then
  3695.     TriggerCollectionEvent _
  3696.         Object:=Item, _
  3697.         Event:="ReplacedItem"
  3698. #End If
  3699.  
  3700.     Set Replace = Me
  3701. End Function
  3702.  
  3703. Public Function Commit() As Long
  3704. Attribute Commit.VB_Description = "Private"
  3705. ' Commit each Object in the collection
  3706. ' Note: although this method is Public, it
  3707. '   should not be executed by any object
  3708. '   other than the governing
  3709. '   VBOFObjectManager
  3710.  
  3711.     Dim tempObject As Object
  3712.     
  3713.     On Local Error Resume Next
  3714.     
  3715. #If NoDebugMode = False Then
  3716.     If pvtVBOFObjectManager.DebugMode Then
  3717.         pvtVBOFObjectManager.DisplayDebugMessage _
  3718.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has begun 'Commit' processing"
  3719.     End If
  3720. #End If
  3721.  
  3722. ' process each object
  3723.     For Each tempObject In pvtCollection
  3724.     
  3725. ' position the RecordSet to correspond to the
  3726. '   current object
  3727.         pvtRecordSet.FindFirst _
  3728.             "ObjectID = " & _
  3729.             tempObject.ObjectID
  3730.             
  3731.         If Err = 0 Then
  3732.             pvtRecordSet.Edit
  3733.             
  3734. ' allow the object to populate the RecordSet
  3735.             tempObject. _
  3736.                 ObjectInitializeRecordSet _
  3737.                     RecordSet:=pvtRecordSet
  3738.         
  3739.             pvtRecordSet.Update
  3740.         End If
  3741.         
  3742.     Next tempObject
  3743.     
  3744. #If NoDebugMode = False Then
  3745.     If pvtVBOFObjectManager.DebugMode Then
  3746.         pvtVBOFObjectManager.DisplayDebugMessage _
  3747.             TypeName(Me) & ", ObjectID=" & Me.ObjectID & ", has completed 'Commit' processing"
  3748.     End If
  3749. #End If
  3750.  
  3751. ' trigger the "Committed" event for the new object
  3752. #If NoEventMgr = False Then
  3753.     TriggerCollectionEvent _
  3754.         Event:="Committed"
  3755. #End If
  3756.  
  3757.     Set tempObject = Nothing
  3758. End Function
  3759. Private Function pvtPositionRecordSetToItem(Optional Item As Variant) As Variant
  3760. Attribute pvtPositionRecordSetToItem.VB_Description = "(Private) internal function"
  3761. ' Position to the RecordSet row which equates to
  3762. '   the specified Item
  3763.  
  3764.     Dim I As Long
  3765.     Dim tempItemFound As Boolean
  3766.     
  3767.     On Local Error Resume Next
  3768.     Err = 0
  3769.     
  3770. ' check the current record first
  3771. '   (performance feature)
  3772.     If Not pvtRecordSet.BOF _
  3773.     And Not pvtRecordSet.EOF _
  3774.     And pvtRecordSet.RecordCount > 0 Then
  3775.         If pvtRecordSet("ObjectID") = CStr(Item.ObjectID) Then
  3776.             Set pvtPositionRecordSetToItem = Item
  3777.             Exit Function
  3778.         End If
  3779.     End If
  3780.     
  3781. ' else, .FindFirst
  3782. '    pvtRecordSet.MoveFirst
  3783.     pvtRecordSet.FindFirst _
  3784.         "ObjectID = " & CStr(Item.ObjectID)
  3785.     
  3786. ' Caution: the application's responses to the
  3787. '   RecordSet might distort the following
  3788. '   processing
  3789.     tempItemFound = _
  3790.         Not pvtRecordSet.NoMatch
  3791.     
  3792. ' This is potentially a very dangerous area (see
  3793. '   preceeding comment).  Make one final check
  3794. '   before returning True
  3795.     If Not tempItemFound _
  3796.     Or pvtRecordSet("ObjectID") <> CStr(Item.ObjectID) Then
  3797.         Set pvtPositionRecordSetToItem = Nothing
  3798.     Else
  3799.         Set pvtPositionRecordSetToItem = Item
  3800.     End If
  3801. End Function
  3802.  
  3803. Private Function TriggerObjectEvent(Optional Object As Variant, Optional Event As Variant) As Boolean
  3804. ' Pass-through to ObjectManager
  3805.     
  3806. #If NoEventMgr = False Then
  3807.     pvtVBOFObjectManager. _
  3808.         TriggerObjectEvent _
  3809.             Event:=Event, _
  3810.             Object:=Object
  3811. #End If
  3812.  
  3813. End Function
  3814.  
  3815. Private Function TriggerCollectionEvent(Optional Object As Variant, Optional Event As Variant, Optional NoDelete As Variant) As Boolean
  3816. ' Pass-through to ObjectManager
  3817.     
  3818. #If NoEventMgr = False Then
  3819.     pvtVBOFObjectManager. _
  3820.         TriggerCollectionEvent _
  3821.             Event:=Event, _
  3822.             Object:=Object, _
  3823.             Collection:=Me, _
  3824.             NoDelete:=NoDelete
  3825. #End If
  3826.  
  3827. End Function
  3828.  
  3829.  
  3830. Private Sub Class_Initialize()
  3831. Attribute Class_Initialize.VB_Description = "Private"
  3832.  
  3833.     Set pvtCollection = New Collection
  3834.     Set pvtSample = Nothing
  3835.     Set pvtParent = Nothing
  3836.     Set pvtDatabase = Nothing
  3837.     Set pvtRecordSet = Nothing
  3838.     Set pvtVBOFObjectManager = Nothing
  3839.     Set pvtMostRecentlyAddedObject = Nothing
  3840.     Set pvtVBOFListBoxWrapper = Nothing
  3841.     Set pvtListBox = Nothing
  3842.     
  3843.     pvtANSISQL = False
  3844.     pvtODBCPassThrough = 0
  3845.     pvtSQLStatement = ""
  3846.     pvtWhereClause = ""
  3847.     pvtDBHasBeenReferenced = False
  3848.     pvtCollectionEmulationMode = True
  3849.     pvtRecordSetProvidedByUser = False
  3850.     pvtSQLStatementProvidedByUser = False
  3851.     pvtDBGridBookmarkArrayAvailable = False
  3852.     pvtAutoDeleteOrphansHasBeenInitialized = False
  3853.     
  3854.     ObjectID = -1
  3855. End Sub
  3856. Public Property Get WhereClause() As String
  3857. Attribute WhereClause.VB_Description = "Sets the WhereClause property"
  3858. ' Returns the current WhereClause value
  3859.     
  3860.     WhereClause = pvtWhereClause
  3861. End Property
  3862.  
  3863. Public Property Let WhereClause(WhereClause As String)
  3864. ' Set the WhereClause to be used in future SQL
  3865. '   Select statements
  3866. ' Note: this step is not necessarily required of
  3867. '   the application
  3868.  
  3869.     pvtReceiveGeneralParameters _
  3870.         WhereClause:=WhereClause
  3871.         
  3872.     pvtCollectionEmulationMode = False
  3873. End Property
  3874.  
  3875. Public Property Get OrderByClause() As String
  3876. Attribute OrderByClause.VB_Description = "Sets the OrderByClause property"
  3877. ' Returns the current OrderByClause
  3878.     
  3879.     OrderByClause = pvtOrderByClause
  3880. End Property
  3881.  
  3882. Public Property Let OrderByClause(OrderByClause As String)
  3883. ' Set the OrderByClause to be used in future SQL Select
  3884. '   statements
  3885. ' Note: this step is not necessarily required of the user
  3886.  
  3887.     pvtReceiveGeneralParameters _
  3888.         OrderByClause:=OrderByClause
  3889.             
  3890.     pvtCollectionEmulationMode = False
  3891. End Property
  3892.  
  3893. Public Property Get Owner() As Variant
  3894. ' Return my owner
  3895.     
  3896. MsgBox "Shouldn't be using 'Owner'.  Use 'Parent' instead."
  3897. '    On Local Error Resume Next
  3898. '
  3899. '    If pvtOwner Is Nothing Or Err = 424 Then
  3900. '        Set Owner = Nothing
  3901. '    Else
  3902. '        Set Owner = pvtOwner
  3903. '    End If
  3904. End Property
  3905.  
  3906. Public Property Set Parent(anObject As Variant)
  3907.     Set pvtParent = anObject
  3908. End Property
  3909.  
  3910. Private Sub Class_Terminate()
  3911. Attribute Class_Terminate.VB_Description = "Private"
  3912.     
  3913.     On Local Error Resume Next
  3914.  
  3915.     pvtCloseRecordSet
  3916.  
  3917. #If NoEventMgr = False Then
  3918.     pvtVBOFObjectManager. _
  3919.         UnRegisterForAllEvents _
  3920.         RegisterObject:=Me
  3921. #End If
  3922.  
  3923.     If Not pvtVBOFObjectManager Is Nothing Then
  3924.         pvtVBOFObjectManager.EmptyCollection _
  3925.             Collection:=Me, _
  3926.             CleanUpMode:=True
  3927.     End If
  3928.  
  3929. End Sub
  3930.  
  3931.  
  3932.  
  3933.  
  3934. Public Function ObjectEventCallBack(Optional Event As Variant, Optional Object As Variant, Optional NoDelete As Variant) As Long
  3935. Attribute ObjectEventCallBack.VB_Description = "Private"
  3936. ' This method is typically invoked when another
  3937. '   VBOFCollection is changing an
  3938. '   item in itself
  3939.  
  3940.     Dim tempObject As Object
  3941.     Dim tempUCaseEvent As String
  3942.     Dim tempNoDelete As Boolean
  3943.     
  3944.     tempUCaseEvent = UCase$(Event)
  3945.     
  3946. ' (performance feature)
  3947. ' check for empty Collection
  3948.     If pvtCollection.Count = 0 Then
  3949.         Exit Function
  3950.     End If
  3951.     
  3952. ' (performance feature)
  3953. ' check the TriggerObject's first object's type
  3954. '   against my first object's type
  3955.     If TypeName(Object) <> _
  3956.         TypeName(pvtCollection.Item(1)) _
  3957.     Then
  3958.         Exit Function
  3959.     End If
  3960.     
  3961.     tempNoDelete = False
  3962.     If Not IsMissing(NoDelete) Then
  3963.         tempNoDelete = NoDelete
  3964.     End If
  3965.     
  3966. ' scan the objects contained herein,
  3967. '   look for the item about which the trigger
  3968. '   is associated
  3969.     For Each tempObject In pvtCollection
  3970.     
  3971.         If tempObject.ObjectID = Object.ObjectID Then
  3972.             
  3973.             If tempUCaseEvent = "REMOVEDITEM" _
  3974.             And Not tempNoDelete Then
  3975.                 pvtCollection.Remove _
  3976.                     CollectionIndex(Item:=tempObject)
  3977.                 
  3978. ' tell any Object Event listeners of the change to
  3979. '   the Collection
  3980. '   (like a GUI, for example)
  3981.                 TriggerObjectEvent _
  3982.                     Object:=Object, _
  3983.                     Event:=Event
  3984.             End If
  3985.              
  3986.             If tempUCaseEvent = "REPLACEDITEM" Then
  3987.                 
  3988. ' tell any Object Event listeners of the change to
  3989. '   the Collection
  3990. '   (like a GUI, for example)
  3991.                 TriggerObjectEvent _
  3992.                     Object:=Object, _
  3993.                     Event:=Event
  3994.             End If
  3995.        End If
  3996.             
  3997.     Next tempObject
  3998.  
  3999.     Set tempObject = Nothing
  4000. End Function
  4001.