VBA Dictionary Multiple Items to Count Col B and Col C

Stephen_IV

Well-known Member
Joined
Mar 17, 2003
Messages
1,168
Office Version
  1. 365
  2. 2019
Platform
  1. Windows
I need VBA assistance. I am using a dictionary to count data. My friend came up with the code below. I am just learning. I have my key as Column A I need to have the item be column B and C to put the output that i need. I am stuck. Any help would be appreciated.

VBA Dic Item Mult Cols.xlsm
ABC
1FacilitySanction Type (primary)Sanction Type (secondary)
214402010700
314781610710
414341910100
514341910649999
614141610100
714761110200
814761110200
914761110610
1014761110201054
1114112010690
1214252010650
1314791610660
1414421910761000
1514291910700
1614291910650
1714761110201010
1814761110201010
Sheet1



VBA Dic Item Mult Cols.xlsm
ABCDEFGHIJKLMN
11070107110101064102010611069106510661076999910541000
21440201000000000000
31478160100000000000
41434190011000000100
51414160010000000000
61476110020510000010
71411200000001000000
81425200000000100000
91479160000000010000
101442190000000001001
111429191000000100000
Sheet2

VBA Code:
Option Explicit
Public Sub main()
Dim lastrow As Long
Dim r As Range
lastrow = Cells(Rows.count, "A").End(xlUp).Row
Set r = Sheets("Sheet1").Range("A2:A" & lastrow)
Dim dic As New Dictionary
Dim dic2 As New Dictionary
Dim dic3 As New Dictionary
Dim dic4 As New Dictionary
Dim dic5 As New Dictionary
Dim xcell
Dim cell
Dim i As Long
Dim j As Long
Dim n As Long
Dim y
    For Each cell In r
        If Not dic.Exists(Trim(cell.Text)) Then
            dic.Add Trim(cell.Text), New Dictionary
        End If
        
        Set dic2 = dic(Trim(cell.Text))
        
        If Not dic2.Exists(Trim(cell.Offset(0, 1).Text)) Then
            dic2(Trim(cell.Offset(0, 1).Text)) = 0
        End If
        
        If Not dic5.Exists(Trim(cell.Offset(0, 2).Text)) Then
            dic5(Trim(cell.Offset(0, 2).Text)) = 0
        End If
        
        dic2(Trim(cell.Offset(0, 1).Text)) = dic2(Trim(cell.Offset(0, 1).Text)) + 1
        dic5(Trim(cell.Offset(0, 2).Text)) = dic5(Trim(cell.Offset(0, 2).Text)) + 1
        dic3(Trim(cell.Offset(0, 1).Text)) = Trim(cell.Offset(0, 1).Text)
        dic5(Trim(cell.Offset(0, 2).Text)) = Trim(cell.Offset(0, 2).Text)
    Next

j = 2
    For Each cell In dic3.Keys
        Sheet2.Cells(1, j).Value = cell
        j = j + 1
    Next

i = 2
    For Each cell In dic.Keys
        j = 2
        Sheet2.Cells(i, 1).Value = cell

Set dic4 = dic(cell)
Dim k
    
    For Each k In dic3.Keys
    Dim count As Integer
    count = 0
        If (dic4.Exists(k)) Then count = dic4(k)
        Sheet2.Cells(i, j).Value = count
        j = j + 1
    Next
        i = i + 1
    Next
End Sub
 

Excel Facts

Format cells as time
Select range and press Ctrl+Shift+2 to format cells as time. (Shift 2 is the @ sign).
It's clear enough but this solution belongs to good readers only …
According to Excel basics like any Excel beginner operating manually a VBA demonstration to paste to the Sheet2 worksheet module :​
VBA Code:
Sub Demo1()
        Dim F$, V, N&
        UsedRange.Clear
        Application.ScreenUpdating = False
    With Sheets("Sheet1").UsedRange.Rows
            F = Replace$("=COUNTIFS(Sheet1!$A$2:$A$#,$A2,Sheet1!$B$2:$B$#,B$1)+COUNTIFS(Sheet1!$A$2:$A$#,$A2,Sheet1!$C$2:$C$#,B$1)", "#", .Count)
        With .Item("2:" & .Count).Columns
           .Item(2).Copy [B1]
            V = Application.Transpose(.Item(3))
        For N = 1 To UBound(V)
            If V(N) = 0 Then V(N) = False
        Next
            V = Filter(V, False, False)
            If UBound(V) > -1 Then Cells(UsedRange.Rows.Count + 1, 2).Resize(UBound(V) + 1).Value2 = Application.Transpose(V)
            UsedRange.RemoveDuplicates 1, 2
            [B1].Resize(, UsedRange.Rows.Count).Value2 = Application.Transpose(UsedRange)
            Range("B2:B" & UsedRange.Rows.Count).Clear
           .Item(1).Copy [A2]
        End With
    End With
        UsedRange.Columns(1).RemoveDuplicates 1, 1
        UsedRange.HorizontalAlignment = xlCenter
    With [B2].Resize(UsedRange.Rows.Count - 1, UsedRange.Columns.Count - 1)
        .Formula = F
        .Formula = .Value2
    End With
        Application.ScreenUpdating = True
End Sub
 
Upvote 0
As using an external object like Dictionary is not always the way to go and here a single Dictionary is necessary only …​
 
Upvote 0
here i used 1 dictionary for the equivalent of both your facility and your sanction and the counters in an array
interested ?
 
Upvote 0
I am using a dictionary to count data. My friend came up with the code below. I am just learning
Your friend did not catch the easy logic !​
A single Dictionary VBA demonstration to paste to the Sheet2 worksheet module :​
VBA Code:
Sub Demo2()
  Const D = "¤", S = "Sheet1"
    Dim H, W, V, R&, C%, K$
        UsedRange.Clear
    With Sheets(S).Range("A2:C" & Sheets(S).UsedRange.Rows.Count).Columns
        H = .Item("B:C").Value2
        W = .Value2
       .Item(1).Copy [A2]
    End With
        UsedRange.RemoveDuplicates 1, 2
    With CreateObject("Scripting.Dictionary")
        For Each V In H:  .Item(V) = Null:  Next
        If .Exists(0) Then .Remove 0
        H = .Keys()
       .RemoveAll
    For R = 1 To UBound(W)
    For C = 2 To 3
        K = W(R, 1) & D & W(R, C)
       .Item(K) = .Item(K) + 1
    Next C, R
        V = UsedRange.Value2
        ReDim W(1 To UBound(V), UBound(H))
    For R = 1 To UBound(V)
    For C = 0 To UBound(H)
        K = V(R, 1) & D & H(C)
        If .Exists(K) Then W(R, C) = .Item(K)
    Next C, R
       .RemoveAll
    End With
        [B1].Resize(, C).Value2 = H
        [B2].Resize(R - 1, C).Value2 = W
        UsedRange.HorizontalAlignment = xlCenter
        Application.ScreenUpdating = True
End Sub
 
Upvote 0
Oups ! I forgot at the beginning of Demo2 just after the codeline UsedRange.Clear this one : Application.ScreenUpdating = False
 
Upvote 0
@Marc L, 3 * Usedrange without a worksheet,
in general a difficult approach.
 
Upvote 0
Usedrange without a worksheet,
in general a difficult approach.
Very not a concern if the VBA procedure is located as expected in the Sheet2 worksheet module !​
Like this the code is lighter : no need to use some useless worksheet object variable or any direct worksheet reference for Sheet2 …​
 
Upvote 0
As the worksheet codenames are used in the original post​
so if really the VBA procedure must be in a general / standard module rather than a worksheet class module this is my Demo2 revamped :​
VBA Code:
Sub Demo2r()
  Const D = "¤"
    Dim H, W, V, R&, C%, K$
        Sheet2.UsedRange.Clear
        Application.ScreenUpdating = False
    With Sheet1.Range("A2:C" & Sheet1.UsedRange.Rows.Count).Columns
        H = .Item("B:C").Value2
        W = .Value2
       .Item(1).Copy Sheet2.[A2]
    End With
        Sheet2.UsedRange.RemoveDuplicates 1, 2
    With CreateObject("Scripting.Dictionary")
        For Each V In H:  .Item(V) = Null:  Next
        If .Exists(0) Then .Remove 0
        H = .Keys()
       .RemoveAll
    For R = 1 To UBound(W)
    For C = 2 To 3
        K = W(R, 1) & D & W(R, C)
       .Item(K) = .Item(K) + 1
    Next C, R
        V = Sheet2.UsedRange.Value2
        ReDim W(1 To UBound(V), UBound(H))
    For R = 1 To UBound(V)
    For C = 0 To UBound(H)
        K = V(R, 1) & D & H(C)
        If .Exists(K) Then W(R, C) = .Item(K)
    Next C, R
       .RemoveAll
    End With
    With Sheet2
        .[B1].Resize(, C).Value2 = H
        .[B2].Resize(R - 1, C).Value2 = W
        .UsedRange.HorizontalAlignment = xlCenter
    End With
        Application.ScreenUpdating = True
End Sub
 
Upvote 0

Forum statistics

Threads
1,215,506
Messages
6,125,193
Members
449,213
Latest member
Kirbito

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