Excel VBA : Why "Sheets" collection is not a "Collection"?

标签 excel vba inheritance collections polymorphism

关于Excel VBA的一个简单问题:如果“Sheets”对象是一个集合,为什么下面的句子返回false? (在中间面板输入)

debug.print TypeOf Sheets Is Collection
Falso

我发现它是因为我创建了一个以 Collection 作为参数的函数。该函数适用于我声明为 Collection 的变量,但不适用于其他集合(例如 Sheets 集合)。

也许 VBA 在继承和/或多态性方面失败了?

<小时/>

编辑:正如JosieP和mehow所解释的,Sheets集合不继承自Collection类/接口(interface),因此它不是一个Collection,并且不能作为Collection进行多态使用。

现在的问题是:为什么 Sheets 不是 Collection 的子类?为什么他们没有从 Collection 继承?考虑到已在 Sheets 中实现的方法/属性,这应该是小菜一碟。正如我所看到的,Collection 类/接口(interface)只需要 4 个方法:

Add
Count
Item
Remove

Sheets 已经实现了 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”都可以通过“foreach”循环以相同的方式进行迭代,但它们不共享公共(public)接口(interface)。如果我必须设计类,层次结构将是:

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

Sheets 将是 cSheets 类的对象(实例)。

通过这种方式,我创建的函数(当前采用 Collection 参数)将采用 iCollection 参数,因此它可以与 Collection 实例和工作表一起使用。

最佳答案

SheetsObject 类型的集合,而不是 Collection 类型的对象。

正如 JosieP 所说

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

应该足够理解了。

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

要确认,请使用 F2 打开对象浏览器,然后输入 find Sheets

<小时/>

向 Microsoft 询问您的第二个问题。但请记住,Collection 可以为空,而 Sheets 始终需要至少有一个 Sheets 或 Chart 对象。

很多东西都依赖于 Excel 中的 Sheets 集合对象,这就是为什么我认为它必须是一个单独的类。我看不出实现 ICollection 接口(interface)并提供单独的实现有什么问题,但就像我说的问 Microsoft(好问题)。

<小时/>

for every 循环是可能的,因为每个 VBA 类都有 attributes 。并非所有属性都可以通过 IDE 看到,但它们确实存在(更多的是 VB6 常识,而不仅仅是引用 VBA)。

好的,现在回答你的第三个问题。您可以迭代集合,因为它实现了 IUnknown 接口(interface) NewEnum()(可枚举方法)。您可以在您的类型的集合上指定默认迭代对象(在 Sheets 情况下为 Sheets 集合)。

参见this link对可枚举方法有更清晰的解释。

参见this answer更好地理解迭代是如何实现的。

关于Excel VBA : Why "Sheets" collection is not a "Collection"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20678834/

相关文章:

c# - 如何使用 epplus 在值大于特定常量值的单元格上添加条件格式

regex - 避免 Excel IF 公式代码中的重复代码

vba - Excel VBA - 匹配 2 列并删除 2 张纸上的重复项

Excel VBA 查找和替换

vba - 我的代码生成一个无限循环

excel - 标记 Excel 列表中剩余的匹配项

.net - 使用 NetOffice 互操作时,无法将 excel 对象作为参数从 VBA 传递到 .NET

ruby - 了解 Ruby 继承

java - 如何指定抽象父字段的子类

java - 停止java中继承树中某些类类型的序列化