我正在尝试了解VBA for Excel中的类模块。我有 cAssociate 类,其中包含名称和数字属性。
GetName(Number as Long)
那样根据号码获取员工的姓名。 我知道如何通过for循环完成这项工作,我想知道如果不循环遍历整个Collection of Associates,这是否可以更好地完成。
答案 0 :(得分:0)
在名为cAssociate的类模块中:
Private pName As String
Private pNumber As Integer
Public Property Let Name(ByRef vName As String)
pName = vName
End Property
Public Property Let Number(ByVal vNumber As Integer)
pNumber = vNumber
End Property
Public Property Get Name() As String
Name = pName
End Property
Public Property Get Number() As Integer
Number = pNumber
End Property
在一个名为cAssociates的类模块中:
Option Explicit
Private assocs As Collection
Private lastID As Integer
Private Sub Class_Initialize()
Set assocs = New Collection
End Sub
Private Sub Class_Terminate()
Set assocs = Nothing
End Sub
Public Sub Add(obj As cAssociate)
lastID = lastID + 1
obj.Number = lastID
assocs.Add obj
End Sub
Public Sub Remove(Index As Variant)
assocs.Remove Index
End Sub
Public Property Get Item(Index As Variant) As cAssociate
Set Item = assocs.Item(Index)
End Property
Property Get Count() As Long
Count = assocs.Count
End Property
Public Sub Clear()
Set assocs = New Collection
End Sub
Public Function GetName(ByVal Number As Long) As String
Dim i As Integer
For i = 1 To assocs.Count
If assocs.Item(i).Number() = Number Then
GetName = assocs.Item(i).Name
Exit Function
End If
Next i
End Function
这是一个测试,放在一个正常的模块中:
Sub TestGetName()
Dim ass As New cAssociates
Dim a As cAssociate
Dim i As Integer
For i = 0 To 10
Set a = New cAssociate
If i = 4 Then
a.Name = "Garry"
Else
a.Name = "Belle"
End If
ass.Add a
Next i
Debug.Print ass.GetName(5)
End Sub
这样做是为了提供一个自定义集合类,为每个新条目分配一个唯一的ID(它的编号)。它有一个额外的方法,允许您通过其ID(称为GetName(整数))
查找名称答案 1 :(得分:0)
这是一个不同的例子,但这是我如何唯一地识别我的类。我在这个CCountries集合类中有一堆CCountry类实例。当我添加它们时
Public Sub Add(clsCountry As CCountry)
If clsCountry.CountryID = 0 Then
clsCountry.CountryID = Me.Count + 1
End If
mcolCountries.Add clsCountry, CStr(clsCountry.CountryID)
End Sub
我为ID属性分配一个序列号,并使用该号码的字符串表示作为我的私人集合中的键。现在我可以通过密钥号
检索任何CCountryPublic Property Get Country(vItem As Variant) As CCountry
Set Country = mcolCountries.Item(vItem)
End Property
请注意,vItem是Variant。如果我传递一个String,它将返回其键为该字符串的Colleciton项。如果我传递一个Long,它将返回Collection中的第n个Item。当你的键是数字的字符串表示时,这可能会导致错误(你认为你得到的键=“10”,但你真的得到第10项),所以要小心。
当你说你想要确保唯一性时,你可能并不意味着像我一样随意分配ID。你可能已经有一个数字,只是不想复制。但是通过将(数字的字符串表示)数字作为集合的关键,它将通过给出重复键错误来确保唯一性。如果你使用Scripting.Dictionary而不是Collection,你可以使用Exists方法来优雅地处理这个问题。
最后,不要轻易放弃循环。是的,有更好的方法,但俗话说'在你衡量之前不要优化'。您可以进行大量的旋转以避免需要一毫秒的循环。拿这个属性
Public Property Get CountryBy(ByVal sProperty As String, ByVal vValue As Variant) As CCountry
Dim clsReturn As CCountry
Dim clsCountry As CCountry
For Each clsCountry In Me
If CallByName(clsCountry, sProperty, VbGet) = vValue Then
Set clsReturn = clsCountry
Exit For
End If
Next clsCountry
Set CountryBy = clsReturn
End Property
它循环,但一旦找到匹配就会停止循环。这仍然意味着要通过整个列表,否则可能意味着在第一个CCountry之后停止。但如果它没有增加性能问题,那么不要浪费你的时间来修复它。