Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary object adding items before .add() is called

I am using a dictionary object from the MS Scripting Runtime library to store a series of arrays and perform operations on the array cells as necessary. There is a for loop to go through the process of creating all of these entries. My issue is that when using the .exists property, it is returning True even before the item has been added.

Closer debugging indicates that the key is being added to the dictionary at the beginning of the for loop, even though no .add command is used and will not be used until the end of the loop.

I have tried a few different configurations, but here is a simple example that fails:

Dim dTotals As Dictionary
Set dTotals = New Dictionary

dTotals.CompareMode = BinaryCompare

For Each cell In rAppID
    If Not dTotals.Exists(cell) Then
    Set rAppIDCells = Find_Range(cell, rAppID)
    Set rAppIDValues = rAppIDCells.Offset(0, 6)
    dAppIDTotal = WorksheetFunction.Sum(rAppIDValues)
    dTotals.Add Key:=cell.Value, Item:=dAppIDTotal
    End If
Next cell

Where each cell contains a string / unique id. At the If statement, the code is returning false, even on the first iteration.

like image 500
riddley_w Avatar asked Jul 09 '12 18:07

riddley_w


2 Answers

I had this problem manifest itself while debugging when I had a watch that attempted to return the "missing" key's item. Actually, further frustrated debugging had the same problem when I literally had a watch for the [scriptingdictonaryObject].exists() condtional); I suggest that the "missing" key is added because of the watch. When I removed the watch and instead created a temporary worksheet to copy the array to while running, the unwanted keys were no longer added.

like image 98
Mike Avatar answered Oct 05 '22 03:10

Mike


In the official documentation‌​ for the scripting runtime it says "If key is not found when attempting to return an existing item, a new key is created and its corresponding item is left empty."

...and yea, when you're debugging in a loop, it appears to pop right out of the sky before the '.exists' function is even called. All is well...

Instead of attempting to add the item that just got added, as in:

dTotals.Add Key:=cell.Value, Item:=dAppIDTotal

...just set the empty object currently at your key to your new one:

dTotals(cell.Value) = dAppIDTotal

So your code block becomes:

If Not dTotals.Exists(cell) Then
    Set rAppIDCells = Find_Range(cell, rAppID)
    Set rAppIDValues = rAppIDCells.Offset(0, 6)
    dAppIDTotal = WorksheetFunction.Sum(rAppIDValues)
    dTotals(cell.Value) = dAppIDTotal
End If

Voila. I tend to rediscover this "feature" on every revisit to VBA. You may also notice the effects of it if you are having a memory leak caused by adding new keys that you do not intend to store.

like image 20
Vic Avatar answered Oct 05 '22 03:10

Vic