Excel 基于唯一属性查找类实例。
我试图学习VBA for Excel中的类模块。我有一个cAssociate类,它具有名称和数字属性Excel 基于唯一属性查找类实例。,excel,vba,class,oop,Excel,Vba,Class,Oop,我试图学习VBA for Excel中的类模块。我有一个cAssociate类,它具有名称和数字属性 有没有办法确保号码保持唯一 最后,我希望能够执行类似于GetName(Number-as-Long)的操作,根据编号获取关联人员的姓名 我知道如何使用for循环来实现这一点,我想知道是否可以以更好的方式实现这一点,而不必在整个关联集合中循环 在名为cAssociate的类模块中: Private pName As String Private pNumber As Integer Pub
- 有没有办法确保号码保持唯一李>
- 最后,我希望能够执行类似于
的操作,根据编号获取关联人员的姓名李>GetName(Number-as-Long)
我知道如何使用for循环来实现这一点,我想知道是否可以以更好的方式实现这一点,而不必在整个关联集合中循环 在名为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(integer))查找名称。这是来自另一个示例,但下面是我如何唯一标识类的方法。我在这个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属性分配一个序列号,并使用该数字的字符串表示形式作为我的私有集合中的键。现在我可以通过密钥编号检索任何国家
Public Property Get Country(vItem As Variant) As CCountry
Set Country = mcolCountries.Item(vItem)
End Property
请注意,vItem是一个变体。如果我传递一个字符串,它将返回其键为该字符串的Colleciton项。如果我传递一个Long,它将返回集合中的第n个项目。当您的键是数字的字符串表示时,这可能会导致错误(您认为您得到的是key=“10”,但实际上得到的是第10项),因此请小心
当你说你想确保唯一性时,你可能并不是想像我一样随意分配ID。你可能已经有了一个号码,只是不想重复。但是,通过将该(字符串表示形式的)数字作为集合的键,它将通过给您一个重复的键错误来确保唯一性。如果使用Scripting.Dictionary而不是集合,则可以使用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
它循环,但一旦找到匹配项就停止循环。这可能仍然意味着浏览整个列表,也可能意味着在第一次访问国家后停止。但是如果它没有增加性能问题,那么就不要浪费时间来解决它。您需要将
Associate
实例存储在某个地方,这样您就可以创建一个Associates
类来保存它们:该类将管理Number
的唯一性并按编号访问名称。在该类中,您可以使用字典来处理某些功能。将其标记为正确,因为答案简单,并且与我的特定用例相关。谢谢谢谢你的回复。我想我的问题不是很清楚。我已经有了每个员工的编号,不需要为他们生成编号。非常详细的回答!