You need to set a reference to the MS Scripting Library to have access to the Dictionary object.
The below code creates a dictionary entry for each year/month. Each entry then holds another dictionary for the names. The count of the child dictionary is the distinct count.
Sub ListDistinctUserCount()
Dim vaValues As Variant
Dim dc As Scripting.Dictionary
Dim dcNames As Scripting.Dictionary
Dim i As Long
Dim sAllData As String
'read range into array
vaValues = Sheet1.Range("A2:D51").Value
Set dc = New Scripting.Dictionary
For i = LBound(vaValues, 1) To UBound(vaValues, 1)
'concat the year and month for dictionary key
sAllData = vaValues(i, 1) & "|" & vaValues(i, 2)
'if it's already added
If dc.Exists(sAllData) Then
'add the name if it doesn't exists
If Not dc.Item(sAllData).Exists(vaValues(i, 4)) Then
dc.Item(sAllData).Add vaValues(i, 4), vaValues(i, 4)
End If
Else
'otherwise add the year month and a new dict for the names
Set dcNames = New Scripting.Dictionary
dcNames.Add vaValues(i, 4), vaValues(i, 4)
dc.Add sAllData, dcNames
End If
Next i
For i = 0 To dc.Count - 1
Debug.Print dc.Keys(i), dc.Items(i).Count
Next i
End Sub
Not very elegant, but I couldn't think of a better way.
Additional Information for VBA Novices
A Variant data type can hold any other data type. It's large and the least efficient, but is necessary in some cases.
The Range.Value
property of a multi-cell range returns a two-dimensional, one-based array. You can assign that array to a Variant and loop through it. This is a lot faster than reading individual cells. Reading and writing to the Excel grid are notoriously slow, so it's a common practice to read a whole range into an array and work with the data that way.
VBA has a Collection object for storing data. The Scripting.Dictionary object has a few features that make it superior such as the .Exists
property and writing all the keys or items out as an array. The Scripting library is installed with Office by default, but is not included in new projects by default. You have to go to Tools - References ton include it.
Dictionaries are key-item lists, like you find in many other languages. The item can be almost any data type. In this case, the item is another dictionary.