Countifs between different Sheets via Dictionary

MK91

New Member
Joined
Jan 10, 2022
Messages
6
Office Version
  1. 2016
Platform
  1. Windows
Dear Excel-Experts,

after failing on my own with various builds, I decided to ask the experts for advice


What do i want to do?

Database
AB
1WS DB
2KEYtoCount
3A222
4B456
5E358
6C125
7H256
8D897
9S799
10C562
11A489
12B456
13A222
14E358
15G114
16F875
17C763
Tabelle1


SHOW
DE
2KEYAmount of toCount (different)
3A2
4B1
5C3
6D1
7E1
Tabelle1


My goal is to fill the column "Amout of toCount (different)" on sheet: "SHOW"

This column should tell me the number of all different "toCount" values of the sheet: "Database".

Example:
Key A
In the database A is mentioned 3 times, but the first and the third time "toCount"-Value is the same (222) so the result is 2.
Key B
mentioned 2 times - both have the same "toCount" -> result = 1
Key C
mentioned 4 times with 3 different "toCount" -> result = 3


I have successfully written a program in which I query a specific key, but I can't manage to convert it to a list (on another sheet):
VBA Code:
Sub simpleCountifDictionary()
    Dim dictX As Object, strX As String, vARR_DB As Variant
    
    Set dictX = CreateObject("scripting.Dictionary")
    
    strX = "EXAMPLE"
    
    Call DB__INFO
    
    With WS_DB
        
        vARR_DB = .Range(.Cells(Z_DB__Start, S_DB__Start), .Cells(Z_DB__End, S_DB__End))
    
        For z = 1 To UBound(vARR_DB)
            If vARR_DB(z, S_DB__Zuo__Person) = strX Then
                dictX(vARR_DB(z, S_DB__PNr)) = vARR_DB(z, S_DB__PNr) + 1
            End If
        Next z

    End With
        
    Debug.Print dictX.Count
End Sub

WS_DB, Z_DB__Start ... are declared in "DB_INFO"
The code example does not exactly match the tables above - they are anoymized. It should only present my progress.


Maybe someone can help me.


Many thanks in Advance
MK91
 

Excel Facts

Test for Multiple Conditions in IF?
Use AND(test, test, test, test) or OR(test, test, test, ...) as the logical_test argument of IF.
Hi @MK91, Thanks for posting on the forum.

Please try the following solution with 2 dictionaries:
VBA Code:
Sub simpleCountifDictionary()
  Dim dic1 As Object, dic2 As Object
  Dim a As Variant
  Dim combo As String
  Dim i As Long
  Dim c As Range
 
  Set dic1 = CreateObject("Scripting.Dictionary")
  Set dic2 = CreateObject("Scripting.Dictionary")
  With Sheets("SHOW")
    a = .Range("A2", .Range("B" & Rows.Count).End(3)).Value
 
    For i = 1 To UBound(a)
      combo = a(i, 1) & "|" & a(i, 2)
      If Not dic1.exists(a(i, 1)) Then
        dic1(a(i, 1)) = 1
        dic2(combo) = Empty
      Else
        If Not dic2.exists(combo) Then
          dic2(combo) = Empty
          dic1(a(i, 1)) = dic1(a(i, 1)) + 1
        End If
      End If
    Next
 
    'Amount of toCount (different) Only from the data in column D
    For Each c In .Range("D2", .Range("D" & Rows.Count).End(3))
      c.Offset(, 1).Value = dic1(c.Value)
    Next
 
    'All KEYS
    .Range("G2").Resize(dic1.Count, 2).Value = Application.Transpose(Array(dic1.keys, dic1.items))
  End With
End Sub


The result in the SHOW sheet like this:
Dante Amor
ABCDEFGH
1KEYtoCountKEYAmount of toCount (different)ALL KEYAmount of toCount (different)
2A222A2A2
3A489B1B1
4B456C3E1
5A222D1C3
6B456E1H1
7E358D1
8C125S1
9H256G1
10D897F1
11S799
12C562
13E358
14G114
15F875
16C763
SHOW


I hope to hear from you soon.
Respectfully
Dante Amor
.
 
Upvote 1
Hey Dante,

thank you very much for your fast answer. Your code is working very well :).

Perhaps you can explain one or two points in more detail so that I can understand them and learn from them.

First:
I don't really understand how you built in range B. The only time you use it is at this position (a(i,2)):
VBA Code:
combo = a(i, 1) & "|" & a(i, 2)

But where/how do you transfer the amount of hits into the dictionary1?



Second:
Can you please explain the role of dic2 explain? I just see how you relate it to "combo" on "Empty" - but I don't understand why.
VBA Code:
dic2(combo) = Empty
VBA Code:
If Not dic2.exists(combo) Then
          dic2(combo) = Empty


Last:
Let's assume the first table would be extended by a column "C" and I also want to have those counted for example in column "F" & "I". Is it possible to modify the code in a simple way?


Finally, thanks again for your help! Your code applied to my application works great, but I would like to understand more of it to master it myself and apply it to other projects.


Kind regards
MK91
 
Upvote 0
Hi @MK91:

I'll explain how it works:

- I have created 2 dictionaries, in dic1 I store the unique values of column A. For example, in the data you have 3 times the letter "A", in dic1 only one letter "A" is stored as an index (this is very important, in the dictionary you store the indices (keys) and you can associate a piece of information (item) with it. In this case, I store the number 1, that is, I start the counter at 1.
VBA Code:
      If Not dic1.exists(a(i, 1)) Then
        'If it doesn't exist, then I add the data to the dictionary and put the number 1 because the counter starts at 1.
        dic1(a(i, 1)) = 1

- 'In something I called "combo" I have the combination of the data from column A and column B
VBA Code:
combo = a(i, 1) & "|" & a(i, 2)
I use the separator "|" between both data, for the following: 1) knowing where data1 is and where data2 is, 2) it is an elegant way to distinguish each data and 3) very important, without the separator it could be that the combination of both can be repeated , for example: data1: AB, data2: 3, combined: AB3
This could be confused with something like data1: A, data2: B3, combined: AB3, you would have 2 times the combination and it is not true.
So the correct is:
AB|3
A|B3

- So in dic2, I store the combo, returning to the example of the letters "A", if the letter "A" does not exist in dic1, it will not exist in dic2 either, that is why I add the combo in dic2 and associate it an emtpy value, since for this scenario a data in the dic2 is not necessary

VBA Code:
      If Not dic1.exists(a(i, 1)) Then
        'If it doesn't exist, then I add the data to the dictionary and put the number 1 because the counter starts at 1.
        dic1(a(i, 1)) = 1
        dic2(combo) = Empty

Example:
varios 09mar2023.xlsm
AB
1KEYtoCount
2A222
SHOW


In the example above, when the reading starts, the letter "A" does not exist in dec1, so it is added to dic1. The combo "A|222", since the letter "A" does not exist, then it is certain that the combo does not exist in dic2, that is why it is added in dic2.
We continue with record 2
varios 09mar2023.xlsm
AB
1KEYtoCount
2A222
3A489
SHOW

VBA Code:
      If Not dic1.exists(a(i, 1)) Then
        dic1(a(i, 1)) = 1
        dic2(combo) = Empty
      Else
        'The letter "A" already exists in Dic1
        If Not dic2.exists(combo) Then
          '"A | 489" not exists, then it is added to dic2
          dic2(combo) = Empty     'with empty since an item is not required
          'As it is a new combo, so we increased the counter of the letter "A", it was at 1, plus 1, so now the counter of "A" is equal to 2.
          dic1(a(i, 1)) = dic1(a(i, 1)) + 1
        End If
      End If
    Next
I hope it helps you.
 
Upvote 0

Forum statistics

Threads
1,214,575
Messages
6,120,334
Members
448,956
Latest member
Adamsxl

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