关于Excel VBA的一个简单问题:如果“Sheets”对象是一个集合,为什么下面的句子返回false? (在中级面板中输入)
debug.print TypeOf Sheets Is Collection
Falso
我发现它是因为我创建了一个以Collection作为参数的函数。该函数适用于我声明为Collection的变量,但不适用于其他集合(例如Sheets集合)。
或许VBA在继承和/或多态性方面失败了?
编辑:正如JosieP和mehow所解释的那样,Sheets集合不会继承Collection类/接口,因此它不是Collection,也不能以多态方式用作Collection 。
所以现在的问题是:为什么Sheets不是Collection的子类?为什么他们没有继承Collection?鉴于已经在Sheets中实现的方法/属性,它应该是小菜一碟。我可以看到,Collection类/接口只需要4个方法:
Add
Count
Item
Remove
表格已经实现了4个类似的方法/属性:
Add
Count
Item
Delete
因此映射将是微不足道的。他们可以轻松地将Sheets集合转换为Collection。
编辑2 :我感谢mehow关于询问MS的建议,但我不会这样做,因为他们可能会说“这不是设计错误,它是一个功能”: )。更多思考的食物:在新工作簿中运行以下代码:
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
我很奇怪“col”和“Sheets”都可以以相同的方式迭代,使用“for each”循环,但它们不共享一个公共接口。如果我必须设计类,层次结构将是:
iIterable (interface)
|
|
iCollection (interface)
/ \
/ \
/ \
Collection cSheets (classes)
和Sheets将是cSheets类的对象(实例)。
通过这种方式,我创建的函数(当前采用Collection参数)将采用iCollection参数,因此它可以与Collection实例和Sheets一起使用。
答案 0 :(得分:6)
Sheets
是Object
类型的集合,而不是Collection
类型的对象。
像JosieP说的那样
Sheets类不会从VBA Collection继承,也不会 实现一个Collection接口(没有Remove方法) 例如)
应该足以理解。
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
要确认打开Object Browser
F2 并输入find Sheets
向Microsoft提出第二个问题。但请记住,Collection
可以为空,而Sheets
始终需要至少有一个表格或图表对象。
很多的东西依赖于Excel中的Sheets集合对象,这就是为什么我认为它必须是一个单独的类。通过实现ICollection接口并提供单独的实现,我看不出有什么问题,但就像我说的那样问微软(好问题)
for each
循环是可能的,因为每个VBA类都有attributes。并非所有属性都可以通过IDE看到,但它们确实存在(更多的VB6常识而不仅仅是对VBA的引用)。
好的,现在回答你的第三个问题。您可以迭代集合,因为它实现了IUnknown接口NewEnum()
( enumarable method )。您在类型集合上指定默认迭代对象(在表格案例中为其Sheets集合)。
有关可枚举方法的更清楚的解释,请参阅this link。
请参阅this answer以更好地了解迭代的可行性。