【问题标题】:VBA Collection with case specific keys带有案例特定键的 VBA 集合
【发布时间】:2023-01-12 04:37:31
【问题描述】:

我需要在 vba 中存储类项,以便可以像普通集合一样对集合进行字符串索引和迭代。但是键需要区分大小写。为了澄清我需要这种行为:

班级:

...
Private mName As String
...
Public Property Get Name() As String
    Name=mName
End Property

Public Property Let Name(RHS As String)
    mName=RHS
End Property
...
Sub DoIt()
    Dim d As Desideratum, foo As classWaz, bar As classWaz, iter As classWaz
    Set d = New Desideratum '<- The thing I need - a collection with case specific keys

    Set foo = New classWaz
    foo.Name = "foo"

    Set bar = New classWaz
    bar.Name = "bar"

    d.Add Item:=foo, Key:="baz"
    d.Add Item:=bar, Key:="BAZ"

    For Each iter In d
        Debug.Print iter.Name
    Next
'Should print
'    foo
'    bar

    Set iter = d("baz")
    Debug.Print iter.Name
'Should print
'    foo

End Sub

设置是我有使用 Collection 的代码,它广泛使用这些习语。但是我在测试时意识到我的用例需要特定于案例的索引,而 Collection 不支持这一点。

我试过Dictionary,但这似乎不支持类项目。 .Items() 也返回一个数组,因此需要不同的迭代习惯用法。而且我不知道有什么方法可以强制Collection 使用vbCompareBinary。即使使用 Option Compare Binay,这也是默认设置。

我可以想到一些解决方法;就像拥有具有 Collection 类型属性的类,而不是具有方法 GetWaz(wazName As String) As classWaz 和未键控的 GetWazes() As Collection。但如果可以的话,我想避免做很多工作。

谢谢

【问题讨论】:

  • 大量修改现有代码。但如果那是唯一的选择,我可以做到。我真的只是在寻找选择。
  • 如果您在将名称用作键之前对其进行哈希处理,那么它们将“区分大小写”(即“AAA”和“aaa”的哈希值不同。例如:stackoverflow.com/a/28362053/478884
  • @TimWilliams - 有趣的想法,但不是真正的选择(我认为),因为我需要能够使用objA.Thing = objB.Things(objA.ThingName)之类的东西来恢复对象。我猜 objA.Thing = objB.Things(hash(objA.ThingName)) 是可能的,但它至少与重做迭代一样笨拙 - 并且存在不同键具有相同散列的边缘情况。谢谢你的想法。

标签: vba


【解决方案1】:

我没有看到使用 Dictionary 的问题:

Sub DoIt()
    ' Requires reference to Microsoft Scripting Runtime
    Dim d As Scripting.Dictionary
    Set d = New Scripting.Dictionary
    
    Dim foo As classWaz, bar As classWaz, iter As classWaz
    Set foo = New classWaz
    foo.Name = "foo"
    
    Set bar = New classWaz
    bar.Name = "bar"
    
    d.Add Key:="baz", Item:=foo
    d.Add Key:="BAZ", Item:=bar
    
    Dim i As Long
    For i = LBound(d.Items) To UBound(d.Items)
        Debug.Print d.Items(i).Name
    Next
    
    Set iter = d("baz")
    Debug.Print iter.Name
End Sub

警告:Scripting.Dictionary 在 macOS 上不可用,尽管您可以考虑这个 drop-in replacement

【讨论】:

  • 一个潜在的问题可能是 Scripting 库在 macOS 上不可用,因此如果代码旨在跨平台,那么这将不起作用。
  • 是的,这肯定是一个警告。
  • 更好的做法是我从一开始就使用 Dictionary,而不是试图从 Collection 中提取字典行为。只是为了可能保存某人的搜索,参考 Microsoft Scripting Runtime 需要使用 Scripting.Dictionary 而不是 CreateObject("Scripting.Dictionay") learn.microsoft.com。这不是我的 Office 安装的默认参考。
猜你喜欢
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
相关资源
最近更新 更多