Can a class extend the Collection object?
Asked Answered
G

4

11

I'm trying to extend functionality of the VBA Collection object in a new class and make this class an inheritant of Collection, but the Implements Collection statement gives me the following error:

Bad interface for Implements: method has underscore in its name.

What underscore?! Add, Item, Remove, and Count are the only methods listed in the documentation for Collection. All four are underscore-free.

EDIT: To clarify, I'm making a class called UniformCollection (that only accepts members that are all of the same type, inspired by this approach). I'd like it to implement Collection, so that a UniformCollection is a Collection and can be used in place of a Collection when calling other objects' methods, etc.

I know I have to write delegating methods/properties for Add, Item, etc., and a NewEnum property for For Each to work, and I've done so already.

My problem is that the Implements Collection statement gives me the error stated above.

Bonus question: is Count a method or a property of Collection? Help calls it a property, but the Object Browser in the VBA editor calls it a function i.e. method (flying yellow box).

Grantee answered 21/4, 2011 at 18:12 Comment(2)
That's a very interesting question. I know you can implement interfaces of built-in classes (for example TextStream). I think @Dick is right that it's the hidden methods/properties that are preventing this for Collection. I've never tried to do this and I never did much with "real" VB or behind the scenes COM stuff, so I don't really know.Trippet
For some related info, but not actually an answer to your question, you can see this addendum page to "Hardcore Visual Basic" by Bruce McKinney: vb.mvps.org/hardweb/mckinney2a.htm . Search on the page for "Page 167", and there is some discussion of the various things VB (and VBA) can't do re: interfaces. That site hosts the whole (out of print) book but I couldn't figure out a way to navigate directly to a page. It's worth buying used for the cost of shipping + $0.01 as a matter of general interest.Trippet
B
8

You are running into one of the limitations of Implements in VBA. You can't implement another class if the other class has any public methods or properties with an underscore in the name. Collection class of course has _NewEnum but any underscore will cause a problem.

For example, if you created a class AddressClass that had the following:

Public Address_City As String

Then created another class CustomerAddress:

Implements AddressClass

Private Property Get ClassInterface_Address_City() As String
End Property

Private Property Let ClassInterface_Address_City(ByVal RHS As String)
End Property

When you compile, you will get an error "Object module needs to implement 'Address_City' for interface 'AddressClass'." Changing the property to AddressCity makes the error go away.

Possible solution: If I understand correctly, you want to implement the collection class so you can pass your new class to methods that take in collections as parameters. Is it possible to alter those methods? My suggestion would be to create your own collection class MyCollection and then implement it instead. i.e. UniformMyCollection That way you can completely avoid problems with underscores.

As for Count, I would trust the Object Browser over the help text anytime. On the other hand, if you are creating your own collection class, it doesn't matter which one you choose.

Bots answered 11/11, 2011 at 7:24 Comment(2)
+1 Good explanation. So the bottom line is, if I understand correctly, that the answer to my question (title) is no?Pond
That is my belief. I suppose some VBA guru might know a way to create an Implements Collection class outside of Excel and then import it in, like the attributes you need to set so NewEnum works correctly, but I don't really think it can be done.Bots
N
6

VBA has a lot of limitations on what classes you can implement. The NewEnum is tripping up Collection, but even if it wasn't, there could very well be something else in that class to trip it up. I think it reports the first problem it finds.

Because Collection has so few properties and methods, I just rewrite them.

Private mcolParts As Collection

Public Sub Add(clsPart As CPart)
    mcolParts.Add clsPart, CStr(clsPart.PartID)
End Sub

Public Property Get Count() As Long
    Count = mcolParts.Count
End Property

Public Property Get Item(vItm As Variant) As CPart
    Set Item = mcolParts.Item(vItm)
End Property

Public Sub Remove(vIndex As Variant)
    mcolParts.Remove vIndex
End Sub

In don't know why the OB shows methods (they look like green boxes to me). For my money, methods either change multiple properties or interact with something outside of the class. Everything else is a property. I'd call both Count and Index properties.

Neary answered 21/4, 2011 at 21:34 Comment(1)
Thanks, but I've already done all this stuff... see clarifying edit.Pond
G
5

Dick Kusleika has most of it, but if you want to use For Each on your custom class, you'll also need:

'--- required additional property that allow to enumerate the collection with For Each
Public Property Get NewEnum() As IUnknown
    Set NewEnum = m_ColParts.[_NewEnum]
End Property

This isn't discussed in either of the links I found in my Favorites (this one or this one), but they're both worth reading. If I find the site that talks about NewEnum I'll do an Edit to add it.

EDIT

Neither of these links are the one I was looking for, either, but both discuss the NewEnum property (including a little extra voodoo that neeeds to be added):

Here and here.

Both of these talk about Excel, but the VBA is the same in other Office applications (including the need for the export->text edit->import process to get "Attributes").

Guttate answered 21/4, 2011 at 23:27 Comment(0)
D
3

Re RolandTumble's note on "NewEnum" :

My own experience in Access 2003 is that "For Each" works fine by importing code including the line

Attribute NewEnum.VB_UserMemId = -4

... but after I "/decompile" the file (command line switch), the line has been removed (verified on export) and the "For Each" does not function.

Unfortunately I need to use "/Decompile" when "Compress and Repair" does not fix things for me.

Delija answered 20/10, 2012 at 23:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.