Home » excel » excel – Creating a Collection as the Value of a Dictionary

excel – Creating a Collection as the Value of a Dictionary

Posted by: admin May 14, 2020 Leave a comment

Questions:

I am trying to create a Dictionary that contains a collection as its value because I have multiple variables, which have different amounts of properties. I was hoping to avoid creating a class.

Sub test()

    Set dict = CreateDict()

    Debug.Print "Done!"
End Sub

Private Function CreateDict() As Scripting.Dictionary
    Set dict = New Scripting.Dictionary
    dict.CompareMode = vbTextCompare


    Set wb = CreateObject("excel.Application").Workbooks.Open("S:\filename.xlsx")
    Set wks = wb.Worksheets(1)

    Row = 2
    Do While IsEmpty(wks.Cells(Row, 1)) = False

        key = wks.Cells(Row, 1)
        value = wks.Cells(Row, 3)

        'Debug.Print key, value

        If dict.Exists(key) Then
            dict(key).Add value
        Else
            Dim col As New Collection
            col.Add value
            dict.Add key, col
        End If

        Row = Row + 1
    Loop

    Workbooks("filename.xlsx").Close savechanges:=False

    Dim key1 As Variant
    For Each key1 In dict.Keys
        Debug.Print key1, dict(key1)(1)
    Next key1

    Set CreateDict = dict
End Function

My keys are added correctly but when I try and access the first value of my collection it is empty, even though if I print value before it is not empty.

I hope I did not do a stupid mistake I just started with VBA a week ago. Any help would be appreciated, also if there is an easier way to do it or if there is an existing way to do this I would be glad to find out.

Thanks in advance

EDIT:

For anyone wondering unfortunately this does not work as stated above, because VBA does not create a new Collection everytime Dim col As New Collection is applied. Instead all values are just added to one Collection col. However I found a workaround, since dynamic variable names are not possible in VBA, according to this post Set variable name with string variable in VBA.

However I just created a function which creates and returns a collection. My code looks now as following:

Sub test()

    Set dict = CreateDict()

    Debug.Print "Done!"
End Sub

Private Function CreateDict() As Scripting.Dictionary
    Set dict = New Scripting.Dictionary
    dict.CompareMode = vbTextCompare


    Set wb = CreateObject("excel.Application").Workbooks.Open("S:\filename.xlsx")
    Set wks = wb.Worksheets(1)

    Row = 2
    Do While IsEmpty(wks.Cells(Row, 1)) = False

        key = wks.Cells(Row, 1)
        value = wks.Cells(Row, 3)

        'Debug.Print key, value

        If dict.Exists(key) Then
            dict(key).Add value
        Else
            dict.Add key, CreateCollection()
            dict(key).Add value
        End If

        Row = Row + 1
    Loop

    Workbooks("filename.xlsx").Close savechanges:=False

    Set CreateDict = dict
End Function

Private Function CreateCollection() As Collection
    Dim col As New Collection
    Set CreateCollection = col
End Function
How to&Answers:

Instead of dict(key1)(0), expand the code as follows:

Dim c as Collection
Set c = dict(key1)
Debug.Print c(1)    ' or c.item(1)

Two issues:

  • Collections are indexed starting at 1
  • VBA sometimes fails to properly resolve chained method calls if it doesn’t have type information.

https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/item-method-visual-basic-for-applications