【问题标题】:VBA - Dictionary Calling Key by Value?VBA - 字典按值调用键?
【发布时间】:2020-06-21 06:29:33
【问题描述】:

似乎这个问题的大部分答案都涉及 C#,所以我觉得问这个问题比较安全:

我需要通过它的值来调用字典键。我有一个包含四个字符键列表的字典对象。例如:

dSCAC.Add "AAAA", 1
dSCAC.Add "BBBB", 2
dSCAC.Add "CCCC", 3
dSCAC.Add "DDDD", 4

等等

当在字符串(在本例中为电子邮件主题行)中找到与键关联的值时,我已经能够调用它,然后从值中添加或删除 1。

例如:检测到 BBBB,值为 2。修改该值并调用相应的键。在这种情况下,最后我们希望 varOtherSCAC = AAAA。

If dSCAC(varSCAC) Mod 2 Then
        Debug.Print "Odd " & "PAPS"
        varOtherSCAC = (dSCAC(varSCAC) + 1)            
        Debug.Print "Opposite SCAC is " & varOtherSCAC

        Else
        Debug.Print "Even " & " PARS"
        varOtherSCAC = (dSCAC(varSCAC) - 1)
        Debug.Print "Opposite SCAC is " & varOtherSCAC
End if

我无法根据这个值计算出调用新键的语法。在VBA中甚至可能吗?有没有办法解决这个问题?

【问题讨论】:

  • 这个的用例是什么?字典通常只确保 key 是唯一的 - 您是否需要键和值都是唯一的?如果没有,是否有规则规定如果有重复,您将返回哪个键?
  • 我目前有一些小项目正在进行中,为了方便更新,我创建了字典作为我需要检查/验证的所有代码是否正确/存在于字符串中的中心位置。在这种情况下,当我发现一个合法代码时,我希望能够快速调用其关联的代码(然后可以将其添加到新字符串并打印)。如果 BBBB 在字符串中,我希望能够找到它的对应项;在这种情况下为 AAAA。每个键/值都必须是唯一的,是的。 AAAA 永远只有 1,BBBB 永远只有 2,等等。
  • 唯一的键/值对与唯一的并不是一回事。换个说法,只有一个 1,只有一个 2,等等。
  • 是的,每个只有一个。

标签: vba outlook


【解决方案1】:

我会采用与@TateGarringer 类似的方法,但将两个Dictionary 对象包装在一个类中,以便为它们提供一个通用接口并使其更易于使用:

'In a class module named MirroredDictionary.cls (add reference to Scripting Runtime)
Option Explicit

Private backing As Scripting.Dictionary
Private mirror As Scripting.Dictionary

Private Sub Class_Initialize()
    Set backing = New Scripting.Dictionary
    Set mirror = New Scripting.Dictionary
End Sub

Public Sub Add(Key As Variant, Value As Variant)
    backing.Add Key, Value
    mirror.Add Value, Key
End Sub

Public Function KeyExists(Key As Variant) As Boolean
    KeyExists = backing.Exists(Key)
End Function

Public Function ValueExists(Value As Variant) As Boolean
    ValueExists = mirror.Exists(Value)
End Function

Public Function ValueFromKey(Key As Variant) As Variant
    ValueFromKey = backing.Item(Key)
End Function

Public Function KeyFromValue(Value As Variant) As Variant
    KeyFromValue = mirror.Item(Value)
End Function

根据您打算如何使用它,您可能想要也可能不想包装额外的功能。用法与普通的Dictionary 类似(除了属性名称的一些差异,尽管您可以更改它们以适应口味):

Public Sub Example()
    Set sample = New MirroredDictionary

    sample.Add "AAAA", 1
    sample.Add "BBBB", 2
    sample.Add "CCCC", 3
    sample.Add "DDDD", 4

    Debug.Print sample.ValueFromKey("AAAA")     '1
    Debug.Print sample.KeyFromValue(1)          'AAAA
    Debug.Print sample.ValueFromKey("BBBB")     '2
    Debug.Print sample.KeyFromValue(2)          'BBBB
    Debug.Print sample.ValueFromKey("CCCC")     '3
    Debug.Print sample.KeyFromValue(3)          'CCCC
    Debug.Print sample.ValueFromKey("DDDD")     '4
    Debug.Print sample.KeyFromValue(4)          'DDDD
End Sub

【讨论】:

  • 我喜欢通用接口的想法,但我以前从未处理过类模块,所以我可能需要一点时间来整理一下。感谢您的帮助!
  • @Kinote 这将是与他们一起玩的绝佳机会。 ;-) 在调试器中逐行浏览示例代码将使您对它的工作原理有一个很好的了解。您基本上是在实现自己的自定义字典类。
  • 编译错误:当我点击类模块时未定义用户定义的类型 - 当它点击第一行时 Private backing As Scripting.Dictionary - 可能都在我头上,语法明智。双字典的概念确实解决了我的问题,使它工作的语法......这需要一段时间。当我的其他模块与之交互时,我偶然发现了我当前的工作。
  • @Kinote 这是顶部的注释 - 您需要添加对 Microsoft Scripting Runtime(更好)或 change it to late binding 的引用。
  • 啊。有点想这就是我所缺少的。我将如何添加对 MSR 的引用?为所有新手问题道歉!
【解决方案2】:

您始终可以创建一个额外的字典来存储您的 Key-Value 对,其中您的 Value 为您的 key,您的 keyvalue

Sub test()
Dim dSCAC As Object
Dim dSCACArr As Object
Dim varOtherSCAC As String
Dim key
Dim varSCAC


Set dSCAC = CreateObject("Scripting.Dictionary")
Set dSCACArr = CreateObject("Scripting.Dictionary")

dSCAC.Add "AAAA", 1
dSCAC.Add "BBBB", 2
dSCAC.Add "CCCC", 3
dSCAC.Add "DDDD", 4

For Each key In dSCAC.Keys
    dSCACArr.Add dSCAC(key), key
Next

For Each varSCAC In dSCAC.Keys
    If dSCAC(varSCAC) Mod 2 Then
            Debug.Print "Odd " & "PAPS"
            varOtherSCAC = dSCACArr(dSCAC(varSCAC) + 1)
            Debug.Print "Opposite SCAC is " & varOtherSCAC

            Else
            Debug.Print "Even " & " PARS"
            varOtherSCAC = dSCACArr(dSCAC(varSCAC) - 1)
            Debug.Print "Opposite SCAC is " & varOtherSCAC
    End If
Next

End Sub

这产生了结果

Odd PAPS
Opposite SCAC is BBBB
Even  PARS
Opposite SCAC is AAAA
Odd PAPS
Opposite SCAC is DDDD
Even  PARS
Opposite SCAC is CCCC

编辑:

For Each varSCAC In dSCAC.Keys...Next 仅用于概念验证。

【讨论】:

  • ReDim dSCACArr(Application.Min(dSCAC.Items) To Application.Max(dSCAC.Items)) 似乎导致运行时错误 438:对象不支持此属性或方法
  • 你完全正确,对不起。我不知道为什么我的大脑直接进入 Excel 函数。您可以通过使用另一个字典来绕过数组方法。我已经修改了我的代码以反映这一点。
  • 不用担心,感谢您的帮助!假设我的搜索返回值 3,我该如何调用 CCCC?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2015-10-10
  • 2017-05-30
  • 2014-06-11
相关资源
最近更新 更多