4

A simple question on Excel VBA: If "Sheets" object is a collection, why the following sentence returns false? (entered at the Inmediate panel)

debug.print TypeOf Sheets Is Collection
Falso

I have discovered it because I made a function that takes a Collection as parameter. The function works with variables that I have declared as Collection, but doesn't work with other collections (such as Sheets collection).

Perhaps VBA is failing in inheritance and/or polymorphism?


Edit: As JosieP and mehow have explained, the Sheets collection doesn't inherits from the Collection class/interface, so it is not a Collection, and can't be used polymorphically as a Collection.

So now the question is: Why Sheets isn't a subclass of Collection? Why they haven't inherited from Collection? It should be a piece of cake, given the methods/properties already implemented into Sheets. As I can see, the Collection class/interface only requires 4 methods:

Add
Count
Item
Remove

And Sheets already implements 4 similar methods/properties:

Add
Count
Item
Delete

So the mapping would be trivial. They could have converted Sheets collection into a Collection easily.


Edit 2: I thank mehow for the suggestion on asking MS, but I won't do it, since they will probably say "it is not a design bug, it is a feature" :). More food for thinking: Run the following code in a new workbook:

Sheets.Add.name = "sh2"
Sheets.Add.name = "sh3"

Dim col As Collection
Set col = New Collection
col.Add Sheets(1)
col.Add Sheets(2)
col.Add Sheets(3)

For Each ele In col
    Debug.Print "ele in col:  " & ele.name
Next ele

For Each ele In Sheets
    Debug.Print "ele in Sheets:  " & ele.name
Next ele

It is strange to me that both "col" and "Sheets" can be iterated the same way, with a "for each" loop, but they don't share a common interface. If I had to design the classes, the hierarchy would be:

    iIterable       (interface)
        |
        |
    iCollection     (interface)
       / \
      /   \
     /     \
Collection  cSheets    (classes)

and Sheets would be an object (instance) of cSheets class.

In this way, the function I made (that currently takes a Collection parameter), would take a iCollection parameter, so it could work both with a Collection instance and with Sheets.

freesoft
  • 1,114
  • 3
  • 17
  • 26
  • 3
    I'm not sure what answer you expect to "why?". the Sheets class does not inherit from the VBA Collection nor does it implement a Collection interface (there is no Remove method for example) – JosieP Dec 19 '13 at 10:24
  • your question is now only answerable by whichever programming team was responsible ;-) – JosieP Dec 19 '13 at 11:12

1 Answers1

7

Sheets is a collection of Object type and not an object of Collection type.

Like JosieP said

the Sheets class does not inherit from the VBA Collection nor does it implement a Collection interface (there is no Remove method for example)

should be enough to understand.

MSDN reference

Sub Main()

    Dim c As Collection
    Set c = New Collection
    
    Debug.Print VarType(c), TypeOf c Is Collection

    Debug.Print VarType(Sheets), TypeOf Sheets Is Object
    
End Sub

To confirm open the Object Browser with F2 and type find Sheets


Address your second question to Microsoft. But bear in mind that Collection can be empty while the Sheets always needs to have at least one Sheets or Chart object.

Lots of things depend on the Sheets collection object in Excel that's why I think it had to be a separate class. I can't see nothing wrong by Implementing ICollection interface and providing a separate implementation but like I said ask Microsoft (good question).


The for each loop is possible because each VBA class has attributes. Not all attributes are visible via the IDE but they do exist (more of VB6 general knowledge than just reference to VBA).

Ok, now to answer your third question. You can iterate over a collection because it implements IUnknown interface NewEnum() (enumarable method). You specify the default iterating object over a collection of your type (in Sheets case its Sheets collection).

See this link for a clearer explanation of the enumerable methods.

See this answer to better understand how the iteration is possible.

double-beep
  • 5,031
  • 17
  • 33
  • 41
  • 4
    + 1 And one more way to check is using `Watch` Window :) – Siddharth Rout Dec 19 '13 at 10:42
  • 2
    a Collection is also an Object so I'm not real sure what that proves? `typeof c is object` also returns True – JosieP Dec 19 '13 at 10:50
  • @JosieP `Sheets` is a collection of `Object` type and not an object of `Collection` type which you have *proved* in your comment which I upvoted :) Didn't want to plagiarise your words so I have explained it differently –  Dec 19 '13 at 11:03
  • 2
    I know that :) my point was that your code doesn't seem to prove anything since `typeof c is object` also returns True just as `typeof Sheets is object` does. the original `typeof Sheets is Collection` actually already proved what I was saying – JosieP Dec 19 '13 at 11:16
  • @SiddharthRout very nice of you to vote to delete my *highly* upvoted [answers](http://stackoverflow.com/questions/16853685/vb-code-for-excel) –  Dec 20 '13 at 00:44
  • @mehow: Which one are you refering to? – Siddharth Rout Dec 20 '13 at 01:11
  • Oh that one? That came up while I was reviewing tasks. Let me make it up to you. You lost 6 votes on that right. :) – Siddharth Rout Dec 20 '13 at 01:12
  • 1
    @mehow: Please don't harass people for voting to delete low-quality questions that you took the time to answer. It was your choice to answer them in the first place. – BoltClock Dec 20 '13 at 06:14
  • And @Siddharth, you know that's just plain serial upvoting. Please don't do that sort of thing again. – BoltClock Dec 20 '13 at 06:17
  • Thank you for the explanation on the (following my proposed hierarchy) "Iterable" interface (IUnknown/NewEnum() in VBA). It is now clear that both Collection class and (in my proposal) "cSheets" class implement the "Iterable" interface. Both clases share a common interface to be iterable. That makes sense. (continued in next comment) – freesoft Dec 20 '13 at 08:36
  • 1
    The thing that doesn't make sense, as we have already discussed, is that they don't share a common interface to be treated as a collection. Both Collection class and cSheets class are collections, but they don't share a common "iCollection" interface. It looks like a big mistake from MS. I know, "ask MS why..." ;-) – freesoft Dec 20 '13 at 08:37
  • 1
    @BoltClock'saUnicorn: Point Taken – Siddharth Rout Dec 20 '13 at 10:38