> ## Content Index
> Fetch the complete content index at: https://nolongerset.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# The Subtle Dictionary Key Bug
- URL: https://nolongerset.com/the-subtle-dictionary-key-bug/
- Published: 2020-12-16T04:59:08.000Z
- Updated: 2026-05-08T13:07:23.000Z
- Description: Always explicitly call the .Value property when using fields or controls as Dictionary keys. Else the bugs come crawling!
- Author: Mike Wolfe
- Tags: Intermediate, Bug Alert, #Import 2026-05-20 02:59

> What's in a key? That which we call a row  
> By any other name should work a treat;  
> \- "*Romeo and Juliet Write VBA"*  
> *(from the lost works of William Shakespeare)*

In a couple of recent articles, I wrote about [collections](https://nolongerset.com/vba-collections-aka-linked-lists/) and [dictionaries](https://nolongerset.com/vba-dictionaries-aka-hash-tables/) in VBA. I wrote about the fundamental differences between the two data structures; collections are linked lists and dictionaries are hash tables.

What I failed to mention was the subtle difference in *keys* between the two.

In collections, the *key* is a string. In dictionaries, the *key* can be anything...or `Nothing` at all.

This difference can lead to subtle bugs, as I detailed in stackoverflow several years ago. I've reproduced the relevant portion of my answer below the link, lightly edited for clarity.

[Bang Notation and Dot Notation in VBA and MS-AccessWhile perusing an application that I’m documenting, I’ve run across some examples of bang notation in accessing object properties/methods, etc. and in other places they use dot notation for what se...![](https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a)Stack OverflowNitrodist![](https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon@2.png?v=73d79a89bded)](https://stackoverflow.com/a/42382616/154439)

---

### What about .Value?

The default *property* for Field objects and most "data-bindable"¹ control objects is `.Value`. Since this is the default property, ~~it's generally considered unnecessarily verbose to always include it explicitly~~ VBA will implicitly return it when the context warrants it. Thus, it's ~~standard~~ common practice to do this:

```vba
Dim EmployeeLastName As String
EmployeeLastName = Me.tbLastName

```

Instead of:

```vba
EmployeeLastName = Me.tbLastName.Value

```

### Beware the subtle .Value bug when keying dictionaries

There are some cases where this convention can cause subtle bugs. The most notable--and, if memory serves, only--one I've actually run into in practice is when using the value of a Field/Control as a Dictionary key.

```vba
Set EmployeePhoneNums = CreateObject("Scripting.Dictionary")
Me.tbLastName.Value = "Jones"
EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-1234"
Me.tbLastName.Value = "Smith"
EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-6789"

```

One would likely expect that the above code creates two entries in the `EmployeePhoneNums` dictionary. Instead, it throws an error on the last line because we are trying to add a duplicate key. That is, the `tbLastName` Control object itself is the key, not the value of the control. In this context, the control's value does not even matter.

In fact, I expect that the object's memory address (`ObjPtr(Me.tbLastName)`) is likely what's being used behind the scenes to index the dictionary. I did a quick test that seems to bear this out.

```vb
'Standard module:
Public testDict As New Scripting.Dictionary
Sub QuickTest()
    Dim key As Variant
    For Each key In testDict.Keys
        Debug.Print ObjPtr(key), testDict.Item(key)
    Next key
End Sub

'Form module:
Private Sub Form_Current()
    testDict(Me.tbLastName) = Me.tbLastName.Value
    Debug.Print ObjPtr(Me.tbLastName); "..."; Me.tbLastName
End Sub

```

When running the above code, exactly one dictionary item is added each time the form is closed and re-opened. Moving from record to record (and thus causing multiple calls to the Form\_Current routine) does not add new dictionary items, because it is the Control object itself indexing the dictionary, and not the Control's value.

---

¹ *What's a "data-bindable" control?*  
*Basically, a control with a `ControlSource` property, such as a TextBox or ComboBox. A non-bindable control would be something like a Label or CommandButton. The default property of both a TextBox and ComboBox is `.Value`; Labels and CommandButtons have no default property.*

---

---

**UPDATE:** I should clarify that the "bug" I referred to above is *NOT* a bug within the Dictionary object's key implementation. Rather, the bug is one that a developer introduces into their own code when they fail to appreciate the difference between how keys are implemented in collections versus dictionaries. The bug is also a side effect of relying on the *implicit* evaluation of the default `.Value` property of fields and controls. Calling `.Value` explicitly when that is the property you intend to use avoids this bug and potentially others. Read more about default values in VBA here: [VBA Trap: Default Members](https://rubberduckvba.wordpress.com/2018/03/15/vba-trap-default-members/).

*Image by [Susanne Jutzeler, suju-foto](https://pixabay.com/users/suju-165106/?utm%5Fsource=link-attribution&utm%5Fmedium=referral&utm%5Fcampaign=image&utm%5Fcontent=5105878) from [Pixabay](https://pixabay.com/?utm%5Fsource=link-attribution&utm%5Fmedium=referral&utm%5Fcampaign=image&utm%5Fcontent=5105878)*