根据唯一属性查找类实例。

时间:2015-07-02 17:35:44

标签: excel vba class oop

我正在尝试了解VBA for Excel中的类模块。我有 cAssociate 类,其中包含名称数字属性。

  • 有没有办法确保号码仍然是唯一的?
  • 最后,我希望能够像GetName(Number as Long)那样根据号码获取员工的姓名。

我知道如何通过for循环完成这项工作,我想知道如果不循环遍历整个Collection of Associates,这是否可以更好地完成。

2 个答案:

答案 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属性分配一个序列号,并使用该号码的字符串表示作为我的私人集合中的键。现在我可以通过密钥号

检索任何CCountry
Public 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之后停止。但如果它没有增加性能问题,那么不要浪费你的时间来修复它。