Solved

Problem retrieving second level from dictionary of dictionaries (VBA in Excel 2007)

Posted on 2010-11-07
2
634 Views
Last Modified: 2012-05-10
I'm trying to employ the dictionary of dictionaries techniques mentioned in a reply to a recent question about storing information where the number of items to be held is unpredictable.  I'm having trouble retrieving the second level dictionary.

To diagnose what was going on I've set up the following code.

Sub TestingDictionaries()

    Dim Phrases As Scripting.Dictionary         '   Dictionary of Phrases
    Dim WordsInPhrase As Scripting.Dictionary   '   Dictionary of the non trivial words in each phrase
    Dim vPhrases As Variant
    Dim vWords As Variant

    Dim iPhrase As Integer, iWord As Integer
    
    Dim wsPhrases As Worksheet
                
    Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "Phrases"
    Set wsPhrases = Worksheets("Phrases") ' List of extracted words
    
    Set Phrases = New Scripting.Dictionary
    Phrases.CompareMode = vbTextCompare

    Set WordsInPhrase = New Scripting.Dictionary
    WordsInPhrase.CompareMode = vbTextCompare
    
'   Load dummy contents

    For iPhrase = 1 To 10
    
        For iWord = 1 To 5
        
            WordsInPhrase.Add iWord, "Word #" & iWord & " in phrase #" & iPhrase
            
        Next iWord
        
'   Dump WordsInPhrase back out to test that it loaded
        
        For iWord = 1 To WordsInPhrase.Count
        
            wsPhrases.Cells(15 + iPhrase + 1, iWord + 2).Value = WordsInPhrase.Item(iWord)
        
        Next iWord
                   
        Phrases.Add "Dummy phrase #" & iPhrase, WordsInPhrase
        WordsInPhrase.RemoveAll
            
    Next iPhrase
    
'   ALL OK TO HERE -------------------------------------------------------

    vPhrases = Phrases.Keys
    
    For iPhrase = 0 To UBound(vPhrases)
    
        wsPhrases.Cells(iPhrase + 1, 1).Value = vPhrases(iPhrase)
        
        Set WordsInPhrase = Phrases.Item(vPhrases(iPhrase))
        
        For iWord = 1 To WordsInPhrase.Count
        
            wsPhrases.Cells(iPhrase + 1, iWord + 2).Value = WordsInPhrase.Item(iWord)
        
        Next iWord
                    
    Next iPhrase

End Sub

Open in new window


Down to the comment "ALL OK TO HERE" it behaves as expected.

The variant vPhrases retrieves the keys to the Phrases dictionary fine and the loop For iPhrase/Next iPhrase behaves as it should but the subsidiary dictionary WordsInPhrase is not retrieved by the line

Set WordsInPhrase = Phrases.Item(vPhrases(iPhrase))

The value of WordsInPhrase.Count is zero

I presume It's a simple error on my part but I'm having trouble tracking it down and any assistance will be most welcome.
0
Comment
Question by:sjgrey
2 Comments
 
LVL 37

Accepted Solution

by:
TommySzalapski earned 500 total points
ID: 34082054
Here is your problem. When you add an item like a scripting dictionary to a dictionary, it doesn't copy the item, it simply adds a reference (or pointer if you're a c programmer). So when you do WordsInPhrase.RemoveAll it removes all the words from both WordsInPhrase and Phrases since it didn't actually copy them in.

See the following code. All I did was change WordsInPhrase to an array and did not clear them. Now it works as expected.
Option Explicit
Private Sub CommandButton1_Click()

    Dim Phrases As Scripting.Dictionary         '   Dictionary of Phrases
    Dim WordsInPhrase(10) As Scripting.Dictionary   '   Dictionary of the non trivial words in each phrase
    Dim vPhrases As Variant
    Dim vWords As Variant

    Dim iPhrase As Integer, iWord As Integer
    
    Dim wsPhrases As Worksheet
                
    Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "Phrases"
    Set wsPhrases = Worksheets("Phrases") ' List of extracted words
    
    Set Phrases = New Scripting.Dictionary
    Phrases.CompareMode = vbTextCompare

'   Load dummy contents

    For iPhrase = 1 To 10
    
        Set WordsInPhrase(iPhrase) = New Scripting.Dictionary
        WordsInPhrase(iPhrase).CompareMode = vbTextCompare
    
        For iWord = 1 To 5
        
            WordsInPhrase(iPhrase).Add iWord + iPhrase, "Word #" & iWord & " in phrase #" & iPhrase
            
        Next iWord
        
'   Dump WordsInPhrase back out to test that it loaded
        
        For iWord = 1 To WordsInPhrase(iPhrase).Count
        
            wsPhrases.Cells(15 + iPhrase + 1, iWord + 2).Value = WordsInPhrase(iPhrase).Item(iWord)
        
        Next iWord
                   
        Phrases.Add "Dummy phrase #" & iPhrase, WordsInPhrase(iPhrase)
        'WordsInPhrase.RemoveAll
            
    Next iPhrase
    
'   ALL OK TO HERE -------------------------------------------------------

    vPhrases = Phrases.Keys
    
    For iPhrase = 0 To UBound(vPhrases)
    
        wsPhrases.Cells(iPhrase + 1, 1).Value = vPhrases(iPhrase)
        
        Set WordsInPhrase(iPhrase) = Phrases.Item(vPhrases(iPhrase))
        
        For iWord = 1 To WordsInPhrase(iPhrase).Count
        
            wsPhrases.Cells(iPhrase + 1, iWord + 2).Value = WordsInPhrase(iPhrase).Item(iWord)
        
        Next iWord
                    
    Next iPhrase

End Sub

Open in new window

0
 
LVL 1

Author Closing Comment

by:sjgrey
ID: 34082121
Great - thanks very much

To maintain the open ended scale of the store, I used Redim Preserve to build the WordsInPhrase array for each new phrase and I think that will solve the problem.
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

My experience with Windows 10 over a one year period and suggestions for smooth operation
When you see single cell contains number and text, and you have to get any date out of it seems like cracking our heads.
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question