VBA:是不是可以创建一个行为类似于集合的类模块?
Posted
技术标签:
【中文标题】VBA:是不是可以创建一个行为类似于集合的类模块?【英文标题】:VBA: Is possible to create a class module which behave like a Collection?VBA:是否可以创建一个行为类似于集合的类模块? 【发布时间】:2020-12-08 14:35:13 【问题描述】:我想知道是否可以创建我自己的类,它的行为就像一个集合。最好在示例中显示:
我目前的知识:
类模块MyClass
Public oCollection As Collection
Public OtherData as Long
... 'Another Variables, Properties, Functions and Subs
模块
...
For Each oItem In MyClass.oCollection 'I need to address Collection inside the object
If oItem.OtherData = 0 Then
...
我想要达到的目标:
...
For Each oItem In MyClass 'Want to be able to iterate over oCollection just from Class
If oItem.OtherData = 0 Then
...
感谢您的建议。
【问题讨论】:
为什么?除了将行减少几个字符并降低可读性(或至少是原始实现的“自我文档”)之外,还有什么好处? 看看here。它将准确显示它是如何完成的,但它也会向您显示 x64 上的相关错误 @sous2817 你可能是对的。我又想了想,我想要它主要是因为我的课程设计不佳。最初的原因是MyClass
props 可以返回“修改”MyClass
,或者修改oCollection
集合。很难(从道具名称)决定返回什么,所以我经常忘记添加.oCollection
,它会抛出错误。但是我没有意识到问题是返回了错误的对象,并且倾向于在属性代码中搜索错误。
【参考方案1】:
您可以通过使用 Scripting.Dictionary 和 .items 或 .Keys 来避免 @CristianBuse 描述的错误。使用 for each 返回可以迭代的数组的方法。
在回答您的问题时,包装集合或脚本字典是一种很好的做法,因为它允许您对主机集合进行强类型化。您还可以使用包装代码为您的输入值添加验证或扩展主机集合的功能
下面的代码显示了脚本字典的包装、add 方法的验证以及简化向脚本字典添加数据的扩展。这些只是说明一点的例子
Option Explicit
Private Type State
Host As scripting.Dictionary
End Type
Private s As State
Private Sub Class_Initialize()
Set s.Host = New scripting.Dictionary
End Sub
Public Property Get Item(ByVal ipKey As Long) As String
Item = s.Host.Item(ipKey)
End Property
Public Property Let Item(ByVal ipValue As String, ByVal ipKey As Long)
s.Host.Item(ipKey) = ipValue
End Property
Public Sub Add(ByVal ipKey As Long, ByVal ipValue As String)
If ipKey > 10 Then
Err.Raise _
5 + vbObjectError, _
"Size Error", _
"Object based on Class " & TypeName(Me) & " is limited to 0-9 members"
End
End If
s.Host.Add ipKey, ipValue
End Sub
Public Sub AddByIndex(ByVal ipArray As Variant)
Dim myArray As Variant
If Not IsArray(ipArray) Then
myArray = Array(ipArray)
Else
myArray = ipArray
End If
Dim myNextKey As Long
myNextKey = s.Host.keys(s.Host.Count - 1)
Do While s.Host.Exists(myNextKey)
myNextKey = myNextKey + 1
Loop
Dim myItem As Variant
For Each myItem In myArray
s.Host.Add myNextKey, myItem
myNextKey = myNextKey + 1
Next
End Sub
Public Function Items() As Variant
Items = s.Host.Items
End Function
所以你现在可以做
oclass.addbyindex Range("A1:A42").value
和
Dim myItem as Variant
For Each myItem in oClass.Items
【讨论】:
将数据包装到 Scripting.Dictionary 似乎是一种有用的技术,但它如何解决Attribute [MethodName].VB_UserMemId = -4
错误?如果我理解正确,最好不要使用VB_UserMemId
属性并直接寻址集合oClass.oCollection
。
你还没看懂我的帖子。使用 scripting.dictionary 不会出现错误,因为在我提供的示例中,您使用 Scripting.Dictionary 的 .Items 方法返回包含项目数组(scripting.dictionary 中的值)和 for 循环的变体遍历提供的 items 数组。以上是关于VBA:是不是可以创建一个行为类似于集合的类模块?的主要内容,如果未能解决你的问题,请参考以下文章
行为类似于 @Entity 和 @Embeddable 的类
iPhone - 行为类似于 UIViewController 的 UIView
Ubuntu中的LibreOffice是不是有类似于Microsoft office(word,excel等)的vba宏的东西? [关闭]