【问题标题】:Excel VBA: Why "Sheets" collection is not a "Collection"?Excel VBA:为什么“表格”集合不是“集合”?
【发布时间】:2013-12-19 10:15:35
【问题描述】:

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

debug.print TypeOf Sheets Is Collection
Falso

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

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


编辑:正如 JosieP 和我所解释的那样,Sheets 集合不继承自 Collection 类/接口,因此它不是一个集合,并且不能多态地用作集合.

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

Add
Count
Item
Remove

而且 Sheets 已经实现了 4 个类似的方法/属性:

Add
Count
Item
Delete

所以映射将是微不足道的。他们可以轻松地将表格集合转换为集合。


编辑 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 一起使用。

【问题讨论】:

  • 我不确定您对“为什么?”的期望是什么。 Sheets 类既不继承自 VBA Collection,也不实现 Collection 接口(例如,没有 Remove 方法)
  • 您的问题现在只能由负责的编程团队来回答 ;-)

标签: excel vba inheritance collections polymorphism


【解决方案1】:

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

就像乔西普说的

Sheets 类既不继承自 VBA 集合,也不继承自 VBA 集合 实现一个 Collection 接口(没有 Remove 方法 例子)

应该足够了解了。

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 打开Object Browser 并键入 find Sheets


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

很多事物依赖于 Excel 中的 Sheets 集合对象,这就是为什么我认为它必须是一个单独的类。通过实现 ICollection 接口并提供单独的实现,我看不出任何问题,但就像我说的问微软(好问题)


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

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

请参阅this link 以更清楚地了解可枚举方法。

请参阅this answer 以更好地了解迭代是如何实现的。

【讨论】:

  • + 1 还有一种检查方法是使用Watch Window :)
  • 集合也是一个对象,所以我不确定这证明了什么? typeof c is object 也返回 True
  • 我知道 :) 我的意思是,您的代码似乎并不能证明任何事情,因为 typeof c is object 也像 typeof Sheets is object 一样返回 True。原来的typeof Sheets is Collection其实已经证明了我的意思
  • @mehow:请不要骚扰人们投票删除您花时间回答的低质量问题。首先回答他们是你的选择。
  • 正如我们已经讨论过的,没有意义的事情是它们不共享一个公共接口来被视为一个集合。 Collection 类和 cSheets 类都是集合,但它们不共享一个通用的“iCollection”接口。这看起来像是 MS 的一个大错误。我知道,“问 MS 为什么......”;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2023-04-02
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
相关资源
最近更新 更多