我创建了一个名为category的类,它有3个属性。 在我的主要课程中,我正在设置10个类型类别的实例。 使用init函数初始化这些对象,以便我可以使用它们 - 现在我想循环遍历这些对象。 我搜索了2个小时,我发现的唯一的事情是,唯一的解决方案是创建这些对象的集合。 您在下面看到我的代码示例:
Dim Kat1 As New category
Dim Kat2 As New category
Dim Kat3 As New category
Dim Kat4 As New category
Dim Kat5 As New category
Dim Kat6 As New category
Dim Kat7 As New category
Dim Kat8 As New category
Dim Kat9 As New category
Dim Kat10 As New category
Dim col As New Collection
Kat1.init "Kat1", 14, 17
Kat2.init "Kat2", 18, 21
Kat3.init "Kat3", 22, 25
Kat4.init "Kat4", 26, 29
Kat5.init "Kat5", 30, 33
Kat6.init "Kat6", 34, 37
Kat7.init "Kat7", 38, 41
Kat8.init "Kat8", 42, 45
Kat9.init "Kat9", 46, 49
Kat10.init "Kat10", 50, 54
col.Add Kat1
col.Add Kat2
col.Add Kat3
col.Add Kat4
col.Add Kat5
col.Add Kat6
col.Add Kat7
col.Add Kat8
col.Add Kat9
col.Add Kat10
For Each col.Item In col
MsgBox (<name of the object>)
Next col.Item
最后一部分似乎不起作用,他在col.item停止错误“参数不是可选的”。
我做错了什么? 请帮帮我
关于
沫
答案 0 :(得分:7)
使用variant
来迭代集合,除非它是定义的数据类型(在这种情况下,变体仍然可以使用)
Dim x As Variant
For Each x In col
MsgBox CStr(x)
Next
代码中的问题是col.Item
不是变量 - 它是从集合中访问项目的方法,因此需要参数。您只能使用变量来迭代For Each
循环
答案 1 :(得分:1)
创建一个函数来启动和返回您的类将大大减少和简化您的代码。您甚至可以考虑创建另一个函数来返回集合。
Sub Main()
Dim Item As Object
For Each Item In getCategoryCollection
MsgBox col.Name
Next col.Item
End Sub
Function getCategoryCollection() As Collection
Dim col As New Collection
col.Add getNewCat("Kat1", 14, 17)
col.Add getNewCat("Kat1", 18, 21)
col.Add getNewCat("Kat1", 22, 25)
col.Add getNewCat("Kat1", 26, 29)
col.Add getNewCat("Kat1", 34, 37)
col.Add getNewCat("Kat1", 38, 41)
col.Add getNewCat("Kat1", 42, 45)
col.Add getNewCat("Kat1", 46, 49)
col.Add getNewCat("Kat1", 50, 54)
End Function
Function getNewCat(CatName As String, CatParam1 As Long, CatParam2 As Long) As Category
Dim Kat1 As New Category
Kat1.init CatName, CatParam1, CatParam2
Set getNewCat = getNewCat
End Function
答案 2 :(得分:0)
四点:
1:收藏品有一个键和一个值:
当你添加一个项目时,给它一个标签 - 密钥 - 可以用于以后的检索:
col.Add Kat10, "Kat10"
如果您不提供钥匙,您的收藏将有序数,因此您可以按号码检索项目;并且您可以随时迭代整个集合,正如Macro Man在他的回答中所示。
2:考虑访问集合的界面:
我假设您显示的代码是某种运行一次的'PopulateCol'函数:将其作为私有声明的对象,并将您的对象公开为公共集合属性:
Option Explicit
Option Private Module
Private colKats as VBA.Collection
Public Property Get Kat(Ident As Variant) as Category
' Return an instance of type 'Category'
' Ident can be numeric (returns by ordinal)
' Ident can be a string (returns by key)
' Caller must deal with errors raised by requests for objects not in the collection
If colKats Is Nothing Then
PopulateCollection
End If
Set Kat = colKats(Ident)
End Property
Public Property Get KatHaus() AS VBA.Collection
'Returns a reference to the collection of Categories
If colKats Is Nothing
Then PopulateCollection
End If
Set KatHaus = colKats
End Property
Private Sub PopulateCol
' Your code here -
End Sub
VBA秘密:在普通模块中声明属性而不是在类模块中,使其成为应用程序级属性 - 始终可见,而无需实例化父对象。
3:内存管理
当存在一个包含对象引用的集合,字典或数组时,我不太相信VBA会清除对象变量的所有内存。
所以我强烈建议你在退出时调用这种代码:
Private Sub ClearKats()
' Remove all the category objects from the collection
Dim i As Long
If colKats Is Nothing Then
Exit Sub
End If
For i = colKats.Count - 1 To 0 Step -1
Set colKats(i) = Nothing ' invokes the class destructor within 'Category'
colKats.Remove(i)
Next i
Set colKats = Nothing
将集合中的对象设置为Nothing需要一些思考:集合的.Item()方法可能返回对象的副本而不是引用 - 您需要测试它!
...这就是拥有一个公共接口的私有集合的真正原因,它始终通过密钥或序数检索:您知道调用者正在获取什么。
在这种情况下,您将获得对“类别”对象的引用,并且每个调用者都会获得对所有当前更改的可编辑和最新对象的引用。也许你想拥有一个严格的只读接口,在你的应用程序中有一个特权进程来维护类别数据,所有调用者都获得只读副本:如果是这样,删除'KatHaus'集合属性并重新实现Kat() 'get'方法从colKats返回基础类别的副本。
考虑使用Dictionary对象而不是VBA集合:
Scripting.Dictionary对象更快,它有一个有用的'Exists()'方法来检查命名项是否在字典中,并且它将Keys和Items公开为可迭代数组。但是,你需要注意Item()和Items()方法返回字典中底层对象的ByVal副本 - 不适合内存管理,如果你需要'live'和可编辑类别类,则不需要
当密钥及其项目尚未出现在字典中时,按键请求项目也会产生令人讨厌的意外:
Set myKat = dicCol("Rover The Dog")
...恭喜,你的代码运行没有错误,并且KatHaus中有一只狗:你创建了一个值为Empty的新项目,当你的下游代码需要一个类型的对象时,它会咬你'类别'。
...因此,字典对象并非没有问题:但它们比VBA集合更快,更通用。
答案 3 :(得分:0)
或者,如果您不想使用变体,可以将迭代器标记为类模块。
例如:Dim temp As category 'Used in the for each loop
注意:我认为您更愿意使用ArrayList对象来存储对象。
以下是使用ArrayList和temp作为对象迭代器
的代码Sub test()
Dim Kat1 As New category
Dim Kat2 As New category
Dim Kat3 As New category
Dim Kat4 As New category
Dim Kat5 As New category
Dim Kat6 As New category
Dim Kat7 As New category
Dim Kat8 As New category
Dim Kat9 As New category
Dim Kat10 As New category
Dim myList As Object 'Used for the arrayList
Dim temp As category 'Used in the for each loop
Set myList = CreateObject("System.Collections.ArrayList")
Kat1.init "Kat1", 14, 17
Kat2.init "Kat2", 18, 21
Kat3.init "Kat3", 22, 25
Kat4.init "Kat4", 26, 29
Kat5.init "Kat5", 30, 33
Kat6.init "Kat6", 34, 37
Kat7.init "Kat7", 38, 41
Kat8.init "Kat8", 42, 45
Kat9.init "Kat9", 46, 49
Kat10.init "Kat10", 50, 54
myList.Add Kat1
myList.Add Kat2
myList.Add Kat3
myList.Add Kat4
myList.Add Kat5
myList.Add Kat6
myList.Add Kat7
myList.Add Kat8
myList.Add Kat9
myList.Add Kat10
For Each temp In myList
MsgBox temp.<name of property>
Next
End Sub