I have pulled down that example this morning. In it, I still find use of hidden Attribute LOC's as follows:
Code:
Function Coll() As Collection
[B][COLOR=Red]Attribute Coll.VB_UserMemId = 0[/COLOR][/B]
Set Coll = Items
End Function
Property Get NewEnum() As IUnknown
[B][COLOR=Red]Attribute NewEnum.VB_UserMemId = -4[/COLOR][/B]
Set NewEnum = Items.[_NewEnum]
End Property
ChrisO, I thought you were objecting to use of those under-the-cover Attribute capabilities. No?
It now appears I have two valid samples of making use of the hidden Attribute LOC's, and those other web pages I located and posted links to in #17.
Aaahhhh... So since an Ordered Collection was desirable, then using the alternate object enumeration syntax suggested in #27 prevented completely need to export / add Attribute LOCs / import?
What would be the correct thing to return on error in the Item method? Your code was:
Code:
Property Get Item(ByVal Index As String) As Variant
If IsObject(Items(Index)) Then
Set Item = Items(Index)
Else
Item = Items(Index)
End If
End Property
My code is:
Code:
Function Item(ByVal strIndex As String) As Variant
On Error GoTo Err_Item
If IsObject(m_PrivateCollection.Item(strIndex)) Then
Set Item = m_PrivateCollection.Item(strIndex)
Else
Item = m_PrivateCollection.Item(strIndex)
End If
Exit_Item:
Exit Function
Err_Item:
Call errorhandler_MsgBox("Class: " & TypeName(Me) & ", Function: Item()")
Resume Exit_Item
End Function
I just realized that the Err_Item: is not returning anything... Oops! Since you suggested testing the stored item with IsObject() and depending on if it is an object or not you selectively use Set, what would be always correct in an error situation?
All right, one further question for when peers get to my questions...
A VBA.Collection appears to respond / look up the correct object out of the collection based on the string key value or the numeric ID assigned by the VBA.Collection object. Is this indeed the way VBA.Collection objects work? If so, I am thinking to switch my Item() method to accept a Variant so that it could support both the String Key or the Long Integer numeric arg being passed in to locate the correct object within the VBA.Collection object.
Thus, it is starting to actually work as intended... that I am getting to asking such detailed questions. Yeaaaa!!!
But Chris, your custom collection wraps around a VBA.Collection and re-exposes exactly what a VBA.Collection exposes. In that case why bother? It's a good demo, but it only makes sense to me to make a custom collection class if you are going to customize the initialization step and/or expose a strongly typed object, otherwise what is gained?
Also, I suggest you don't create anything until you have to, so rather than Class_Initialize, consider this code...
Code:
Private m_items As VBA.Collection
Property Get Items as VBA.Collection
[COLOR="Green"]' Don't create this object until a consumer specifically requests it.
' This becomes more important if you actually create a strongly typed
' collection of custom objects, and if a parent class contains a few of those.
' So my cCustomer class might have a custom cOrders collection, a
' cPayments collection, a cEmployees collection, but don't build them
' when created, wait until until a consumer actually demands one
[/COLOR] if m_items is nothing then set m_items = GetCollection
set Items = m_items
Private Function GetCollection as VBA.Collection
[COLOR="Green"]' Do this custom initialization INSIDE your custom collection . . .[/COLOR]
Set GetCollection = New VBA.Collection
GetCollection.Add "A", "1"
GetCollection.Add "B", "2"
End Function
Now you've automated your initialization of a custom collection class and given it a reason to exist beyond simply wrapping an existing class.
Or this code, which exposes strongly typed items in it's Item() property . . .
Code:
[SIZE="1"]Private m_items As VBA.Collection
Private m_sf As cSnapForm
Private Property Get Items() As VBA.Collection
If m_items Is Nothing Then CreateCollection
Set Items = m_items
End Property
Property Get Item(index) As cSnapSide
Set Item = Items(index)
End Property
Property Get Count() As Long
Count = Items.Count
End Property
Function Load(Form As cSnapForm) As cSnapSides
Set m_sf = Form
Set Load = Me
End Function
Private Sub CreateCollection()
Dim css As cSnapSide
Dim i As Byte
Set m_items = New VBA.Collection
For i = 1 To 4
Set css = New cSnapSide
css.Load m_sf, i
m_items.Add css
Next
End Sub[/SIZE]
. . . and I don't want there to be an Add() method. Access.Form.Controls and DAO.Recordset.Fields don't have, and don't need, Add() methods.
Post #44.
>>What would be the correct thing to return on error in the Item method? Your code was:<<
No, that was Galaxiom’s code not mine. I’m not saying I disagree with it, just that it is not mine.
>>Since you suggested testing the stored item with IsObject() and depending on if it is an object or not you selectively use Set, what would be always correct in an error situation?<<
Again, that code is not mine and I try to avoid words like ‘always’.
Many times you will see it said on the www that all procedures should have error handling in them. That is not correct. Many people do not put error handling in Class modules but, rather, let the caller of the Class handle the error.
But this thread is about “Enumeration through a collection in a custom class” not about error handling. Error handling is a whole new bucket of bolts.
Post #45
>>A VBA.Collection appears to respond / look up the correct object out of the collection based on the string key value or the numeric ID assigned by the VBA.Collection object. Is this indeed the way VBA.Collection objects work?<<
From post #46
>> But Chris, your custom collection wraps around a VBA.Collection and re-exposes exactly what a VBA.Collection exposes. In that case why bother?<<
Indeed, why bother? This thread is about “Enumeration through a collection in a custom class” and, as yet, we don’t even know what will be going into the Collection or how it will be used.
So why bother going to all the trouble of hiding information in the Class header and also requiring another reference?
It might be clever code but it might also be too clever under the circumstances, which we do not know.
Indeed, why bother? This thread is about “Enumeration through a collection in a custom class” and, as yet, we don’t even know what will be going into the Collection or how it will be used.
To answer both of these at the same time, per my OP I referenced where I got the original design. Thus, per that example, this collection only holds one custom class type. So since the VBA.Collection is completely encapsulated (I decided against adding the Items() method which would return the raw VBA.Collection object), it can never have a non Object in it, so I will remove that IsObject() check, and thus have the Err_Item: return using the Set keyword.
Post #45
>>A VBA.Collection appears to respond / look up the correct object out of the collection based on the string key value or the numeric ID assigned by the VBA.Collection object. Is this indeed the way VBA.Collection objects work?<<