Excel 基于唯一属性查找类实例。

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

我试图学习VBA for Excel中的类模块。我有一个cAssociate类,它具有名称数字属性

  • 有没有办法确保号码保持唯一
  • 最后,我希望能够执行类似于
    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
的唯一性并按编号访问名称。在该类中,您可以使用字典来处理某些功能。将其标记为正确,因为答案简单,并且与我的特定用例相关。谢谢谢谢你的回复。我想我的问题不是很清楚。我已经有了每个员工的编号,不需要为他们生成编号。非常详细的回答!