Add class to dictionary

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,834
Office Version
  1. 365
  2. 2019
Platform
  1. Windows
In the following code to find unique values and aggregate amounts and volumes:

Code:
Option Explicit
Sub Start()
    Dim dict As Scripting.Dictionary
Set dict = ReadData

End Sub

Function ReadData() As Dictionary
    Dim dict As Scripting.Dictionary
Set dict = New Scripting.Dictionary

Dim rg As Range
Set rg = Sheet1.Range("A1").CurrentRegion

Dim i As Long, CustomerID As String, Amount As Currency
Dim Volume As Long, oCustomer As Class1

For i = 2 To rg.Rows.Count

CustomerID = rg.Cells(i, 1).Value

Amount = rg.Cells(i, 4).Value
Volume = rg.Cells(i, 5).Value

If dict.Exists(CustomerID) Then

Set oCustomer = dict(CustomerID)

Else

Set oCustomer = New Class1

dict.Add CustomerID, oCustomer

End If

oCustomer.Amount = oCustomer.Amount + Amount
oCustomer.Volume = oCustomer.Volume + Volume

    Next i
    Set ReadData = dict

End Function


This is Class1:

Code:
Option Explicit

Private pAmount As Currency
Private pVolume As Long
Public Property Get Amount() As Currency
    Amount = pAmount

End Property
Public Property Let Amount(ByVal vNewValue As Currency)
    pAmount = vNewValue
End Property
Public Property Get Volume() As Long
    Volume = pVolume

End Property
Public Property Let Volume(ByVal vNewValue As Long)
    pVolume = vNewValue

End Property

can someone please explain this line:

Code:
If dict.Exists(CustomerID) Then
Set oCustomer = dict(CustomerID) 'PUZZLES ME ?????
Else
Set oCustomer = New Class1
dict.Add CustomerID, oCustomer
End If

I understand that if the dictionary with the key CustomerID DOES NOT exist, then create a new instance of Class1 and add this instance of Class1 to the dictionary with CustomerID as the key but if the key CustomerID DOES exist, what is "Set oCustomer = dict(CustomerID)" doing?

Thanks
 

Excel Facts

Copy formula down without changing references
If you have =SUM(F2:F49) in F50; type Alt+' in F51 to copy =SUM(F2:F49) to F51, leaving the formula in edit mode. Change SUM to COUNT.
dict(CustomerID) returns the class object associated with CustomerID. The class object is then assigned to oCustomer, which is an object variable that is capable of holding a class object of the same type.
 
Upvote 0
dict(CustomerID) returns the class object associated with CustomerID. The class object is then assigned to oCustomer, which is an object variable that is capable of holding a class object of the same type.

I understand what you mean by:

"The class object is then assigned to oCustomer, which is an object variable that is capable of holding a class object of the same type."

but what do you mean a the start, namely:

dict(CustomerID) returns the class object associated with CustomerID.
 
Upvote 0
Let's say that the key is "A", and that the item is a class object (ie oCustomer). So, as you know, we first add an item to the dictionary like this...

VBA Code:
dict.add key:="A", item:=oCustomer

... or if you prefer, without named arguments...

VBA Code:
dict.add "A", oCustomer

Then we can retrieve the item, in this case the class object, by using the Item method and passing it a key...

VBA Code:
dict.Item("A")  --> returns the item (ie. the class object) associated with the key (ie. "A")

Note that you can also do it this way...

VBA Code:
dict("A") --> also returns the item associated with the key

The Item method is implicit.

***EDITED***

So this means that we can assign the returned object to an object variable of the same type and access the properties like this...

VBA Code:
Set oCustomer = dict("A")
debug.print oCustomer.Amount
debug.print oCustomer.Volume

...or we can also access them directly like this...

VBA Code:
debug.print dict("A").Amount
debug.print dict("A").Volumne

Hope this helps!
 
Last edited:
Upvote 0
Let's say that the key is "A", and that the item is a class object (ie oCustomer). So, as you know, we first add an item to the dictionary like this...

VBA Code:
dict.add key:="A", item:=oCustomer

... or if you prefer, without named arguments...

VBA Code:
dict.add "A", oCustomer

Then we can retrieve the item, in this case the class object, by using the Item method and passing it a key...

VBA Code:
dict.Item("A")  --> returns the item (ie. the class object) associated with the key (ie. "A")

Note that you can also do it this way...

VBA Code:
dict("A") --> also returns the item associated with the key

The Item method is implicit.

Hope this helps!


Great, I get it now, thanks.
 
Upvote 0
Please have a look at my edited post.

Cheers!


Yes very clear.

My problem with OOP is that reading material often states:

Code:
Dim dict As Scripting.Dictionary

then it talks about instantiating dict like:

Code:
Set dict = New Scripting.Dictionary

However as in the original code at the start of the post, we actually have:

Code:
Dim dict As Scripting.Dictionary
Set dict = ReadData

obviously ReadData is function of TYPE dictionary, otherwise you'd get a compile error.

It's these techniques that I find books tend to gloss over and not explain in greater detail.
 
Upvote 0
However as in the original code at the start of the post, we actually have:

Code:
Dim dict As Scripting.Dictionary
Set dict = ReadData

obviously ReadData is function of TYPE dictionary, otherwise you'd get a compile error.

I guess, more precisely, ReadData is a function that returns a dictionary object. So ReadData actually creates the dictionary object, not the calling procedure. Then, it adds items to the collection, then it returns the dictionary object to calling procedure, and then it's assigned to the object variable dict, which is declared as a Dictionary object, and so capable of holding an object of that type.
 
Upvote 0
I guess, more precisely, ReadData is a function that returns a dictionary object. So ReadData actually creates the dictionary object, not the calling procedure. Then, it adds items to the collection, then it returns the dictionary object to calling procedure, and then it's assigned to the object variable dict, which is declared as a Dictionary object, and so capable of holding an object of that type.

Very thorough, couldn't have made it any clearer, thanks!

at times, I tend to view (incorrectly) programming to be like maths, eg ax+ay = a(x+y).

So in the code, as I see:

Code:
Dim dict As Scripting.Dictionary

in Sub Start and I also see it in Function ReadData() As Dictionary, I instinctively think I could have declared dict at the module level but would be wrong.
 
Upvote 0
in Sub Start and I also see it in Function ReadData() As Dictionary, I instinctively think I could have declared dict at the module level but would be wrong.

Actually, the dictionary object could have been declared at the module level, and then both procedure and function, along with any other procedures or functions in the module, would have direct access to it. So there would be no need to pass the dictionary object from the function back to the calling procedure. However, it's considered poor programming practice. :)
 
Upvote 0

Forum statistics

Threads
1,214,979
Messages
6,122,561
Members
449,089
Latest member
Motoracer88

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top