我一直在尝试清理代码,使其与Excel对象模型更相似,我想知道是否有可能在VBA中创建“可循环”容器类,例如类似于您的操作方式:
Dim Sheet As Worksheet
For Each Sheet In ThisWorkbook.Worksheets
' ...
Next Sheet
我想要我自己的容器使用此功能。
假设我创建了自己的名为Container
的类,其中包含某个类ItemType
的项目(在该示例中,这可以是一个空类):
' Class Container
' The container contains items of a class I will call ItemType
Private Type MContainer
Items As Collection ' Could also be implemented in terms of an array
End Type
Private This As MContainer
Public Property Get Item(ByVal Index As Long) As ItemType
Attribute Item.VB_UserMemId = 0 'Makes it so I can access elements like a Collection
Set Item = This.Items(Index)
End Property
Public Function Add() As ItemType
This.Items.Add
Set Add = This.Items(This.Items.Count)
End Function
Private Sub Class_Initialize()
Set This.Items = New Collection
End Sub
然后,我想使用For Each...
遍历容器中的项目,但这不起作用。请参阅以下示例,了解我理想情况下的工作方式:
Public Sub MyMethod()
Dim Stuff As New Container
Stuff.Add
Dim Element As ItemType
For Each Element In Stuff ' <- This will not work
' Do something
Next Element
End Sub
最后一个For
循环是我要进行的工作。这可能吗?基本上,问题是我无法在我的For Each
类上调用Container
,类似于您使用类似的方法Excel.Sheets
类。这可以在VBA中实现吗?
答案 0 :(得分:3)
将此添加到您的班级
Public Function NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Set NewEnum = Items .[_NewEnum]
End Function
答案 1 :(得分:3)
For Each
迭代需要一个特殊的成员属性值才能工作,并且需要一个NewEnum
属性或函数才能返回IUnknown
。
每个可以通过For Each
循环进行迭代的集合类都具有一个隐藏的[_NewEnum]
成员(访问该隐藏成员需要方括号,因为下划线前缀对于VBA中的标识符是非法的
无法直接在VBE中进行模块和成员属性的调整,因此您需要删除/导出模块,然后在其中进行修改。 Notepad ++,保存更改,然后将其重新导入到您的项目中。
或者让Rubberduck(免责声明:我为这个开源项目做出了贡献)使用注释(又称“魔术评论”)为您完成此任务:
'@Enumerator
'@Description("Gets an enumerator that iterates through the internal object collection.")
Public Property Get NewEnum() As IUnknown
Set NewEnum = this.Items.[_NewEnum]
End Function
'@DefaultMember
'@Description("Gets/sets the element at the specified index.")
Public Property Get Item(ByVal index As Long) As ItemType
Set Item = this.Items(index)
End Property
然后解析项目( Ctrl + `)并打开 Inspection Results 工具窗口( Ctrl + Shift + i )-在“ Rubberduck机会”下应该有许多“缺少属性”结果:
在底部窗格中单击“修复模块中的所有匹配项”,以将隐藏的属性与注释注释同步。
如果结果为“缺少注释”,Rubberduck已确定模块/成员具有给定属性的非默认值,并能够类似地添加注释注释,该注释注释/带有注释的表面/文档。 / p>
代码资源管理器( Ctrl + R ),Rubberduck工具栏和VBE自己的对象浏览器 ( F2 )将显示VB_Description
属性的内容,因此@Description
批注在任何公共过程中特别有用。
对象浏览器:
代码资源管理器:
Rubberduck工具栏:
答案 2 :(得分:0)
解决此问题的另一种方法是不使用Collection,而是使用Scripting.Dictionary。脚本字典的优点之一是它可以返回字典的键和项的数组。在VBA中遍历数组是一项微不足道的练习。