VBA: Using Dictionary or Arrays to sum based on multiple columns?

Coyotex3

Active Member
Joined
Dec 12, 2021
Messages
496
Office Version
  1. 365
Platform
  1. Windows
Hi, I've been working on consolidating some data and was wondering what is the best approach using VBA Dictionaries or arrays to go from this range:

Book1
ABCDE
1DateNameLocationBonusAmount
210/12/2023John DoeNew York0381
310/12/2023Jane DoeNew York0126
410/12/2023Jack DoeNew York0272
510/12/2023John DoeNew York0522
610/12/2023Jane DoeNew York0745
710/13/2023John DoeNew York0144
810/13/2023Jane DoeNew York0754
910/13/2023Jack DoeNew York0263
1010/13/2023John DoeNew York0103
1110/13/2023Jane DoeNew York0525
12
13
Sheet1


To this range which contains a unique list of values based on Columns A:C(Date, Name, Location), and the fourth columns gives you the total amount for each combination(A sumifs in essence).

Book1
JKLM
1DateNameLocationAmount
210/12/2023John DoeNew York903
310/12/2023Jane DoeNew York871
410/12/2023Jack DoeNew York272
510/13/2023John DoeNew York247
610/13/2023Jane DoeNew York1279
710/13/2023Jack DoeNew York263
8
9
Sheet1
 

Excel Facts

Which came first: VisiCalc or Lotus 1-2-3?
Dan Bricklin and Bob Frankston debuted VisiCalc in 1979 as a Visible Calculator. Lotus 1-2-3 debuted in the early 1980's, from Mitch Kapor.
It can be done with a formula, or are you specifically looking for VBA?

Book1
JKLM
1DateNameLocationAmount
210/12/2023John DoeNew York903
310/12/2023Jane DoeNew York871
410/12/2023Jack DoeNew York272
510/13/2023John DoeNew York247
610/13/2023Jane DoeNew York1279
710/13/2023Jack DoeNew York263
8
Sheet7
Cell Formulas
RangeFormula
J2:M7J2=LET(u,UNIQUE(A2:C11),a,INDEX(u,0,1),b,INDEX(u,0,2),c,INDEX(u,0,3),CHOOSE({1,2,3,4},a,b,c,SUMIFS(E2:E11,A2:A11,a,B2:B11,b,C2:C11,c)))
Dynamic array formulas.
 
Upvote 0
It can be done with a formula, or are you specifically looking for VBA?

Book1
JKLM
1DateNameLocationAmount
210/12/2023John DoeNew York903
310/12/2023Jane DoeNew York871
410/12/2023Jack DoeNew York272
510/13/2023John DoeNew York247
610/13/2023Jane DoeNew York1279
710/13/2023Jack DoeNew York263
8
Sheet7
Cell Formulas
RangeFormula
J2:M7J2=LET(u,UNIQUE(A2:C11),a,INDEX(u,0,1),b,INDEX(u,0,2),c,INDEX(u,0,3),CHOOSE({1,2,3,4},a,b,c,SUMIFS(E2:E11,A2:A11,a,B2:B11,b,C2:C11,c)))
Dynamic array formulas.
Hi Eric, thank you for this. Looking specifically for VBA as I'm working on updating an existing code.

I was provided this code before which worked for what I needed. This one looked at a list of items in Column A, and ran calculations based of Column A. Have not been able to figure out a way of adding columns B and C to the If Not .Exists argument. Unsure if it can even be done.

VBA Code:
Sub Example)
 Dim ar, a, i As Long
 ar = Cells(1).CurrentRegion
 
 With CreateObject("scripting.dictionary")
   For i = 2 To UBound(ar)
     If Not .Exists(ar(i, 1)) Then
       .Item(ar(i, 1)) = Array(ar(i, 1), ar(i, 2), ar(i, 3))
     Else
       a = .Item(ar(i, 1))
       a(2) = a(2) + ar(i, 3)
       .Item(ar(i, 1)) = a
     End If
   Next
   Cells(1, 8).Resize(.Count, 3) = Application.Index(.items, 0, 0)
 End With
End Sub
 
Upvote 0
How about this?

EXCEL
ABCDEFGHIJ
1DateNameLocationBonusAmount
210/12/2023John DoeNew York038110/12/2023John DoeNew York903
310/12/2023Jane DoeNew York012610/12/2023Jane DoeNew York871
410/12/2023Jack DoeNew York027210/12/2023Jack DoeNew York272
510/12/2023John DoeNew York052210/13/2023John DoeNew York247
610/12/2023Jane DoeNew York074510/13/2023Jane DoeNew York1279
710/13/2023John DoeNew York014410/13/2023Jack DoeNew York263
810/13/2023Jane DoeNew York0754
910/13/2023Jack DoeNew York0263
1010/13/2023John DoeNew York0103
1110/13/2023Jane DoeNew York0525
Sheet3


VBA Code:
Sub test()
Dim r As Range:         Set r = Range("A2:E" & Range("A" & Rows.Count).End(xlUp).Row)
Dim AR() As Variant:    AR = r.Value2
Dim SD As Object:       Set SD = CreateObject("Scripting.Dictionary")

For i = 1 To UBound(AR)
    tmp = Join(Array(AR(i, 1), AR(i, 2), AR(i, 3)), ",")
    SD(tmp) = SD(tmp) + AR(i, 5)
Next i

Set r = Range("G2").Resize(SD.Count)
r.Value = Application.Transpose(SD.keys)
r.TextToColumns DataType:=xlDelimited, comma:=True

Set r = r.Offset(, UBound(AR, 2) - 2)
r.Value = Application.Transpose(SD.items)
End Sub
 
Upvote 0
Solution
lrobbo314 beat me to it, but here's my take, similar in concept:

VBA Code:
Sub Coyotex3()
Dim ar As Variant, d As Object
Dim i As Long, k As Variant, out() As Variant, x As Variant

    ar = Cells(1).CurrentRegion
    
    Set d = CreateObject("Scripting.Dictionary")
    For i = 2 To UBound(ar)
        k = ar(i, 1) & "|" & ar(i, 2) & "|" & ar(i, 3)
        d(k) = d(k) + ar(i, 5)
    Next i
    
    ReDim out(1 To d.Count, 1 To 4)
    i = 0
    For Each x In d
        k = Split(x, "|")
        i = i + 1
        out(i, 1) = k(0)
        out(i, 2) = k(1)
        out(i, 3) = k(2)
        out(i, 4) = d(x)
    Next x
    
    Cells(2, "J").Resize(d.Count, 4) = out
            
End Sub
 
Upvote 1
Some other options that may be considered if you have the GROUPBY function available. If you don't you should get sometime before too long.
I know that you don't want a formula approach but I have included one in Q1 (results spill into Q:T).
The GROUPBY function has lots of options so for a vba approach I have included a couple of those with results in G:I (basic grouping) and L:O (sorted ascending by date and descending by name and total included).

VBA Code:
Sub GroupAndSum1()
  Dim d As Range
  
  Set d = Range("A1").CurrentRegion
  Range("G1").Formula2 = "=GROUPBY(" & d.Resize(, 3).Address & "," & d.Columns(5).Address & ",SUM,3,0)"
  With Range("G1").SpillingToRange
    .Value = .Value
    .Cells(1, 4).Value = d.Cells(1, 5).Value
  End With
End Sub

Sub GroupAndSum2()
  Dim d As Range
  
  Set d = Range("A1").CurrentRegion
  Range("L1").Formula2 = "=GROUPBY(" & d.Resize(, 3).Address & "," & d.Columns(5).Address & ",SUM,3,1,{1,-2})"
  With Range("L1").SpillingToRange
    .Value = .Value
    .Cells(1, 4).Value = d.Cells(1, 5).Value
  End With
End Sub

Coyotex3_1.xlsm
ABCDEFGHIJKLMNOPQRST
1DateNameLocationBonusAmountDateNameLocationAmountDateNameLocationAmountDateNameLocation
212/10/2023John DoeNew York038112/10/2023Jack DoeNew York27212/10/2023John DoeNew York90312/10/2023John DoeNew York903
312/10/2023Jane DoeNew York012612/10/2023Jane DoeNew York87112/10/2023Jane DoeNew York87112/10/2023Jane DoeNew York871
412/10/2023Jack DoeNew York027212/10/2023John DoeNew York90312/10/2023Jack DoeNew York27212/10/2023Jack DoeNew York272
512/10/2023John DoeNew York052213/10/2023Jack DoeNew York26313/10/2023John DoeNew York24713/10/2023John DoeNew York247
612/10/2023Jane DoeNew York074513/10/2023Jane DoeNew York127913/10/2023Jane DoeNew York127913/10/2023Jane DoeNew York1279
713/10/2023John DoeNew York014413/10/2023John DoeNew York24713/10/2023Jack DoeNew York26313/10/2023Jack DoeNew York263
813/10/2023Jane DoeNew York0754Total3835Total3835
913/10/2023Jack DoeNew York0263
1013/10/2023John DoeNew York0103
1113/10/2023Jane DoeNew York0525
12
Sheet1
Cell Formulas
RangeFormula
Q1:T8Q1=GROUPBY(A1:C11,E1:E11,SUM,3,1,{1,-2})
Dynamic array formulas.
 
Upvote 0
Some other options that may be considered if you have the GROUPBY function available. If you don't you should get sometime before too long.
I know that you don't want a formula approach but I have included one in Q1 (results spill into Q:T).
The GROUPBY function has lots of options so for a vba approach I have included a couple of those with results in G:I (basic grouping) and L:O (sorted ascending by date and descending by name and total included).

VBA Code:
Sub GroupAndSum1()
  Dim d As Range
 
  Set d = Range("A1").CurrentRegion
  Range("G1").Formula2 = "=GROUPBY(" & d.Resize(, 3).Address & "," & d.Columns(5).Address & ",SUM,3,0)"
  With Range("G1").SpillingToRange
    .Value = .Value
    .Cells(1, 4).Value = d.Cells(1, 5).Value
  End With
End Sub

Sub GroupAndSum2()
  Dim d As Range
 
  Set d = Range("A1").CurrentRegion
  Range("L1").Formula2 = "=GROUPBY(" & d.Resize(, 3).Address & "," & d.Columns(5).Address & ",SUM,3,1,{1,-2})"
  With Range("L1").SpillingToRange
    .Value = .Value
    .Cells(1, 4).Value = d.Cells(1, 5).Value
  End With
End Sub

Coyotex3_1.xlsm
ABCDEFGHIJKLMNOPQRST
1DateNameLocationBonusAmountDateNameLocationAmountDateNameLocationAmountDateNameLocation
212/10/2023John DoeNew York038112/10/2023Jack DoeNew York27212/10/2023John DoeNew York90312/10/2023John DoeNew York903
312/10/2023Jane DoeNew York012612/10/2023Jane DoeNew York87112/10/2023Jane DoeNew York87112/10/2023Jane DoeNew York871
412/10/2023Jack DoeNew York027212/10/2023John DoeNew York90312/10/2023Jack DoeNew York27212/10/2023Jack DoeNew York272
512/10/2023John DoeNew York052213/10/2023Jack DoeNew York26313/10/2023John DoeNew York24713/10/2023John DoeNew York247
612/10/2023Jane DoeNew York074513/10/2023Jane DoeNew York127913/10/2023Jane DoeNew York127913/10/2023Jane DoeNew York1279
713/10/2023John DoeNew York014413/10/2023John DoeNew York24713/10/2023Jack DoeNew York26313/10/2023Jack DoeNew York263
813/10/2023Jane DoeNew York0754Total3835Total3835
913/10/2023Jack DoeNew York0263
1013/10/2023John DoeNew York0103
1113/10/2023Jane DoeNew York0525
12
Sheet1
Cell Formulas
RangeFormula
Q1:T8Q1=GROUPBY(A1:C11,E1:E11,SUM,3,1,{1,-2})
Dynamic array formulas.
Peter thanks for this option! Sadly I do not have GroupBy available yet. Still waiting for those to be available to regular users!
 
Upvote 0

Forum statistics

Threads
1,215,071
Messages
6,122,963
Members
449,094
Latest member
Anshu121

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