VBA take at least 1 test with over 350,000 rows

Stephen_IV

Well-known Member
Joined
Mar 17, 2003
Messages
1,168
Office Version
  1. 365
  2. 2019
Platform
  1. Windows
I have over 350,000 rows of data and need to count how many students per school who have taken at least 1 test. I have the data set below. Thanks in advance.

VBA Frequency Count if any test is taken.xlsm
ABCDEFGHIJ
1SchoolNameTestIDStart
2AAA*****, *******test 11110AAA1
3AAA*****, *******test 21110BBB2
4AAA*****, *******test 31110CCC0
5AAA*****, *******test 41110
6AAA*****, *******test 51110
7AAA*****, *******test 61110
8AAA*****, *******test 71110
9AAA*****, *******test 81110
10AAA*****, *******test 91110
11AAA*****, *******test 101110
12BBB*****, *****test 12220
13BBB*****, *****test 22221
14BBB*****, *****test 32220
15BBB*****, *****test 42221
16BBB*****, *****test 52220
17BBB*****, *****test 62220
18BBB*****, *****test 72221
19BBB*****, *****test 82220
20BBB*****, *****test 92220
21BBB*****, *****test 102220
22AAA********, ******test 13330
23AAA********, ******test 23330
24AAA********, ******test 33330
25AAA********, ******test 43330
26AAA********, ******test 53330
27AAA********, ******test 63330
28AAA********, ******test 73331
29CCC******, ****test 14440
30CCC******, ****test 24440
31CCC******, ****test 34440
32CCC******, ****test 44440
33CCC******, ****test 54440
34CCC******, ****test 64440
35CCC******, ****test 74440
36BBB*******, *****test 15550
37BBB*******, *****test 25551
38BBB*******, *****test 35550
39BBB*******, *****test 45550
40BBB*******, *****test 55551
41BBB*******, *****test 65550
42BBB*******, *****test 75550
Sheet2
 

Excel Facts

Do you hate GETPIVOTDATA?
Prevent GETPIVOTDATA. Select inside a PivotTable. In the Analyze tab of the ribbon, open the dropown next to Options and turn it off
Try:

VBA Code:
Sub TestTakers()
Dim MyData As Variant, OutData() As Variant, MyDic As Object
Dim i As Long, x As Variant

    MyData = Range("A2:E42").Value
    Set MyDic = CreateObject("Scripting.Dictionary")
    
    For i = 1 To UBound(MyData)
        If Not MyDic.exists(MyData(i, 1)) Then
            Set MyDic(MyData(i, 1)) = CreateObject("Scripting.Dictionary")
        End If
        MyDic(MyData(i, 1))(MyData(i, 4)) = 1
    Next i
    
    i = 1
    ReDim OutData(1 To MyDic.Count, 1 To 2)
    For Each x In MyDic
        OutData(i, 1) = x
        OutData(i, 2) = MyDic(x).Count
        i = i + 1
    Next x
    
    Range("I2").Resize(MyDic.Count, 2).Value = OutData
        
End Sub

Change the range in the first line to be the entire input range, and change the range in the last line to be where you want the results.
 
Upvote 0
Hi Eric thanks for the reply,

Your code is giving me the result of

AAA2
BBB2
CCC1

The result I am looking for is

AAA1
BBB2
CCC0

for example the first school AAA id# 111 and start = all 0's does not get counted because the student did not start a test.
 
Upvote 0
@Stephen_IV
Assuming data is sorted by col ID, try this:
VBA Code:
Sub Stephen_IV()
Dim flag As Boolean
Dim i As Long, j As Long
Dim va
Dim d As Object

va = Range("A1:E" & Cells(Rows.Count, "A").End(xlUp).Row)

        Set d = CreateObject("scripting.dictionary")
        d.CompareMode = vbTextCompare
 
For i = 2 To UBound(va, 1)
 j = i
    flag = False
    Do
        If flag = False Then
            If va(i, 5) <> 0 Then
               d(va(i, 1)) = d(va(i, 1)) + 1
                flag = True
            End If
        End If
            i = i + 1
        If i > UBound(va, 1) Then Exit Do
    Loop While va(i, 4) = va(i - 1, 4)
    i = i - 1

Next

'Put the result at G2
Range("g2").Resize(d.Count, 2) = Application.Transpose(Array(d.Keys, d.Items))
End Sub
 
Upvote 0
Akuini,

That did the trick! Thank you and Eric W so much for the help.
 
Upvote 0
Just for the record, here's how to adjust mine to handle the 0 values in column E:

Rich (BB code):
Sub TestTakers()
Dim MyData As Variant, OutData() As Variant, MyDic As Object
Dim i As Long, x As Variant

    MyData = Range("A2:E42").Value
    Set MyDic = CreateObject("Scripting.Dictionary")
    
    For i = 1 To UBound(MyData)
        If Not MyDic.exists(MyData(i, 1)) Then
            Set MyDic(MyData(i, 1)) = CreateObject("Scripting.Dictionary")
        End If
        If MyData(i, 5) > 0 Then MyDic(MyData(i, 1))(MyData(i, 4)) = 1
    Next i
    
    i = 1
    ReDim OutData(1 To MyDic.Count, 1 To 2)
    For Each x In MyDic
        OutData(i, 1) = x
        OutData(i, 2) = MyDic(x).Count
        i = i + 1
    Next x
    
    Range("I2").Resize(MyDic.Count, 2).Value = OutData
        
End Sub

Glad you got a solution.
 
Upvote 0
Thanks Eric! I always appreciate any help I can get!
 
Last edited:
Upvote 0

Forum statistics

Threads
1,214,573
Messages
6,120,318
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