Reputation: 175
Is there any way to find the key that corresponds to a given item in a VBA dictionary?
http://msdn.microsoft.com/en-us/library/aa164502%28v=office.10%29.aspx MSDN suggests that the "Key" property can be used, but when I try using it I get an error ("Compile error: invalid use of property"). I've found in the past that the "Exists" method given here doesn't work for me either, so I assume that they were the commands in a previous version of Office and are now outdated. However I haven't been able to find an equivalent for the latest version of Office.
I could use a for each loop to create a new dictionary where the keys in the old dictionary are the items in the new dictionary (and vice versa) and then use ".Item", but I was wondering if there was an inbuilt command that would allow me to avoid this.
Upvotes: 4
Views: 38488
Reputation: 1
From this, I first thought that .exists(key) is enterely useless. But there IS an easy circumvention.
First, let me mention a futile attempt:
Well, that works, but the next time you test for existence again with this code
itExists = a.exists(key)
you may get a 424 error -- the implementor of .exists REALLY failed. But the following will work (or at least, for me it does... so far)
if isempty(a.item(key)) then ' checking on value of the object
a.remove(key)
a.add key, value
else ' you have a key duplicate
' do something about dupe, like quit
end if
For a little clarification, you can look at the following example code below
Sub aDict()
Dim a As Dictionary
Dim x As Long
Set a = New Dictionary
With a
On Error Resume Next
' first add
.Add 1, "sumpn"
' second add
.Add "dog", "beagle"
x = 66
' third add
.Add "sixty", x
printd a, 1, "added with numerical key"
printd a, 2, "added with string key = dog, using numeric key=2"
Stop ' look at count of items: we added 3, but have 4 in local vars
printd a, "2", "searching string key '2', not retrieving 2nd added"
printd a, 9, "should not exist, first try"
' but the .exists has created it!!
printd a, 9, "should not exist, second try, *** but now created ***"
printd a, 8, "never seen anywhere"
Stop ' look at a in local vars!! #8 exists now as item 7
a.Remove 8 ' so we kill it
' *************************** the great fixit *******
Stop ' observe that #8 (item 7) is gone again
printd a, "dog", "added as second position (Item 2)"
' fourth add
.Add 1, "else" ' doublette
printd a, 1, "position 1 is taken, Err=457 is correct"
' fifth add
.Add 3, "beagle"
printd a, "3", "string key='3' <> numeric 3"
' 6th add
.Add 5, "beagle"
printd a, "beagle", "value is already there with key 'dog'"
printd a, 5, "numeric key=5"
End With
End Sub
Sub printd(a As Dictionary, mkey, Optional msg As String)
Dim ex As Boolean
With a
If Err.number <> 0 Then
Debug.Print mkey, "error " & Err.number, Err.Description
End If
Err.clear
ex = .Exists(mkey) ' very first reference to a.Exists(mkey)
Debug.Print "key " & mkey, "a(" & mkey & ")" & a(mkey), _
"Exists", ex, "a.item " & .Item(mkey), msg
If Err.number <> 0 Then
Debug.Print mkey, "error " & Err.number, Err.Description
End If
End With
End Sub
Upvotes: 0
Reputation: 61
Actually, there is an Exists method that will do exactly what you want. Here's how it works:
...
Dim dict
Set dict = CreateObject("Scripting.Dictionary")
dict.Add "utensil", "spork"
Debug.Print dict.Exists("utensil")
The above returns True.
Upvotes: 0
Reputation: 1093
An alternate solution(..?)
Instead of going through each item in the dictionary for a match, how about you maintain 2 dictionary objects? The second one, using value as the key and key as its value. When u add an item, u add it both the dictionaries. If you have a key, you look it up in the first dictionary and if you have the value, u look it up in the second one.
Upvotes: 4
Reputation: 149287
but I was wondering if there was an inbuilt command that would allow me to avoid this.
Nope there is no inbuilt command as such. You will have to resort to some kind of looping. Here is one example. I created a small function to get the key corresponding to an item in a dictionary.
Dim Dict As Dictionary
Sub Sample()
Set Dict = New Dictionary
With Dict
.CompareMode = vbBinaryCompare
For i = 1 To 10
.Add i, "Item " & i
Next i
End With
Debug.Print GetKey(Dict, "Item 3")
End Sub
Function GetKey(Dic As Dictionary, strItem As String) As String
Dim key As Variant
For Each key In Dic.Keys
If Dic.Item(key) = strItem Then
GetKey = CStr(key)
Exit Function
End If
Next
End Function
Upvotes: 12