19

This is not working for me, and it is unclear why.

Sub mySub()
    dim myDict as Dictionary
    myDict=new Dictionary
            
    myDict=myFunc()
                
End Sub
        
Function myFunc()
    dim myDict2
    set myDict2 = new Dictionary
                    
    'some code that does things and adds to myDict2'
                    
    myFunc=myDict2
End Function

How can I return a dictionary from a function?

jordanz
  • 367
  • 4
  • 12
jason m
  • 6,519
  • 20
  • 69
  • 122

2 Answers2

45

You'll need to use the SET keyword anytime you are assigning an object instead of a value:

    Sub mySub()
        dim myDict as Dictionary
        set myDict = myFunc()
    End Sub

    Function myFunc() as Dictionary
        dim myDict2 as Dictionary
        set myDict2 = new Dictionary
                'some code that does things and adds to myDict2'
        set myFunc=myDict2
    End Function

Your original code was also creating myDict as a new Dictionary object, then immediately replacing it with a different one. You can just skip that step.

BradC
  • 39,306
  • 13
  • 73
  • 89
  • this works with a slight alteration if you set myFunc(1)=myDict2. but then this creates an infinite loop. – jason m Oct 27 '10 at 22:05
  • 1
    No, its not an infinite loop. `myFunction = Value` (or `SET myFunction = Object`) is the VBA equivalent of `RETURN Value` – BradC Oct 27 '10 at 22:09
  • And you don't want `myFunc(1)=`, you just want `myFunc=`, otherwise you're just setting the first value of the dictionary to the entire other object, which isn't what you want. – BradC Oct 27 '10 at 22:13
  • yes the "Set myFunction=Obj" is the bit of code that was required. thank you very much for the pointer – jason m Oct 28 '10 at 11:08
  • While using the same code..I am getting error as user-defined type not defined.Please help – user3206357 May 27 '16 at 05:24
  • Sorry, @user3206357, I don't know anything about the object libraries that this original user had installed, or whether "Dictionary" is a custom object he defined himself. I was just correcting a syntax error he had when trying to return that object. – BradC May 27 '16 at 17:32
  • @user3206357 you need to import microsoft scripting runtime. see http://stackoverflow.com/questions/3233203/how-do-i-use-filesystemobject-in-vba – jason m Jun 14 '16 at 22:31
0

I see that this is an old question, but the post AND solution helped me figure this out, and I took it to the next level. It was a small leap. Thank you!

How about converting your function that populates the dictionary with process names and IDs so it returns a dictionary object? Then it is a simple task of populating a sheet with the dictionary contents, which I learned to do from a blog. I wish I had the author's name but the link is included.

Sheet1 was assumed of course. Customize however you wish. Again this was a small leap from what both of you posted. Absolutely brilliant work guys, thank you!

Sub Test_AllRunningApps()
    Dim apps As Dictionary
    Set apps = AllRunningApps()

    'Populate a sheet with a dictionary - http://exceldevelopmentplatform.blogspot.com/2018/05/vba-writing-dictionaries-to-worksheet.html
    Sheet1.Cells(1, 1).Resize(apps.Count, 1).Value2 = Application.Transpose(apps.Keys)
    Sheet1.Cells(1, 2).Resize(apps.Count, 1).Value2 = Application.Transpose(apps.Items)

    Set apps = Nothing
End Sub

'Similar to: http://msdn.microsoft.com/en-us/library/aa393618%28VS.85%29.aspx
Public Function AllRunningApps() As Dictionary
    Dim strComputer As String
    Dim objServices As Object, objProcessSet As Object, Process As Object
    Dim oDic As Object, oDic2 As Object, a() As Variant

    Set oDic = CreateObject("Scripting.Dictionary")

    strComputer = "."

    Set objServices = GetObject("winmgmts:\\" _
        & strComputer & "\root\CIMV2")
    Set objProcessSet = objServices.ExecQuery _
        ("Select Name, ProcessID FROM Win32_Process", , 48)

    For Each Process In objProcessSet
       If Not oDic.exists(Process.Name) Then
        oDic.Add Key:=Process.Properties_("Name").Value, Item:=Process.Properties_("ProcessID").Value
       End If
    Next

    Set AllRunningApps = oDic

    Set objProcessSet = Nothing
    Set oDic = Nothing
End Function
HopWorks
  • 468
  • 1
  • 5
  • 13
  • I also realized that the way the dictionaries are initialized requires you to include references in your workbook/VBA. I always include three...Microsoft Script Control 1.0, Microsoft Scripting Runtime, Microsoft Scriptlet Library – HopWorks Sep 08 '19 at 00:04