Top Subset of Category with Most Recent as Tie Breaker

MagiCarty

New Member
Joined
Oct 4, 2013
Messages
12
I'm trying to pull back (based on Customer Number), their #1 Case Reason based on volume of cases, and then when there is a tie (like for 3CTI001-S or 3RTT001), bring back the most recent Case Reason as the winner (from the top tied groups).

I'm thinking there are some arrays and countifs involved here, but my brain hurts from the hours trying to figure this out. Many thanks for your help.



Excel 2010
ABCDEF
1Customer NumberCase ReasonDate/Time OpenedCustomer NumberTop Reason (should be)
2101W001-SInstallation3/7/2016 9:07101W001-SInstallation
3101W001-SInstallation3/7/2016 6:153CTI001Hardware Tech Support
4101W001-SInstallation2/24/2016 8:573CTI001-SHardware Tech Support
5101W001-SSoftware Tech Support6/30/2016 7:553DCO001Software Tech Support
6101W001-SSoftware Tech Support6/10/2016 5:543RTT001General Account Maintenance
73CTI001Software Tech Support9/22/2016 16:35405T001Installation
83CTI001General Account Maintenance3/16/2016 14:15
93CTI001Installation9/15/2016 13:19
103CTI001Hardware Tech Support7/14/2016 8:36
113CTI001Hardware Tech Support9/6/2016 12:24
123CTI001Hardware Tech Support9/1/2016 13:48
133CTI001-SGeneral Account Maintenance3/15/2016 13:24
143CTI001-SGeneral Inquiries2/2/2016 9:57
153CTI001-SHardware Tech Support3/30/2016 9:39
163DCO001Hardware Tech Support10/31/2016 9:21
173DCO001Hardware Tech Support10/31/2016 9:12
183DCO001Software Tech Support8/17/2016 8:27
193GCO001Software Tech Support10/31/2016 12:32
203GCO001Software Tech Support8/17/2016 8:27
213GCO001Software Tech Support8/9/2016 14:11
223RTT001General Account Maintenance11/11/2016 12:19
233RTT001General Account Maintenance9/6/2016 6:26
243RTT001General Inquiries7/14/2016 10:15
253RTT001General Inquiries7/11/2016 5:46
263RTT001Installation8/24/2016 12:37
273RTT001Installation7/9/2016 7:50
283RTT001Hardware Tech Support12/1/2016 9:39
29405T001Finance6/16/2016 13:42
30405T001Installation1/22/2016 13:39
31405T001Installation1/22/2016 12:06
32405T001Installation1/22/2016 11:17
33405T001Installation1/22/2016 9:48
test
 
Last edited:
Here's a macro that should work for you.

1) Open a copy of your workbook
2) Right click on the sheet tab on the bottom and select View Code
3) From the menu, select Insert > Module
4) Paste this code into the sheet that opens:
Rich (BB code):
Sub GetReasons()
Dim ResultRow As Long, Cust As String, t As Long, i As Long, MyTable As Variant

    Application.ScreenUpdating = False
    Columns("E:F").ClearContents    Range("E1").Value = "Customer"
    Range("F1").Value = "Top Reason"
    
    ResultRow = 2
    MyTable = Range("A2:C" & Cells(Rows.Count, "A").End(xlUp).Row).Value
    Cust = MyTable(1, 1)
    t = 1
    
    For i = 1 To UBound(MyTable)
        If MyTable(i, 1) <> Cust Then
            Call DoReason(MyTable, Cust, t, i - 1, ResultRow)
            t = i
            Cust = MyTable(i, 1)
        End If
    Next i
    Call DoReason(MyTable, Cust, t, i - 1, ResultRow)
    
    Application.ScreenUpdating = True
        
End Sub


Sub DoReason(MyTable, Cust, t, b, MyRow)
Dim MyDict As Object, i As Long, d As String, w As Variant, m As Double, x As Variant, y As Double

    Set MyDict = CreateObject("Scripting.Dictionary")
    For i = t To b
        d = MyTable(i, 2)
        If MyDict.exists(d) Then
            w = Split(MyDict.Item(d), Chr(9))
            MyDict.Item(d) = CDbl(w(0)) + 100000 & Chr(9) & IIf(CDbl(MyTable(i, 3)) > CDbl(w(1)), CDbl(MyTable(i, 3)), w(1))
        Else
            MyDict.Add d, 100000 & Chr(9) & CDbl(MyTable(i, 3))
        End If
    Next i
    
    d = ""
    m = 0
    For Each x In MyDict
        w = Split(MyDict.Item(x), Chr(9))
        y = CDbl(w(0)) + CDbl(w(1))
        If y > m Then
            m = y
            d = x
        End If
    Next x
    
    Cells(MyRow, "E") = Cust
    Cells(MyRow, "F") = d
    MyRow = MyRow + 1
            
End Sub
5) Tweak to match your workbook. In particular, the items in red. This macro does assume that the sheet with the data on it is active, and that the customers are in groups.
6) Press Alt-Q to exit the VBA editor
7) Press Alt-F8 to open the macro selector, choose GetReasons and click Run.

Let me know how that works. In particular, I'm curious how long it takes. On my machine, with this limited data, it takes no time at all. On a full sized data set, I couldn't say.
 
Last edited:
Upvote 0

Excel Facts

Copy formula down without changing references
If you have =SUM(F2:F49) in F50; type Alt+' in F51 to copy =SUM(F2:F49) to F51, leaving the formula in edit mode. Change SUM to COUNT.
This version might be a bit faster:

Rich (BB code):
Sub GetReasons()
Dim ResultRow As Long, Cust As String, t As Long, i As Long, MyTable As Variant, OutTable As Variant


    Application.ScreenUpdating = False
    Columns("E:F").ClearContents
    
    ResultRow = 2
    MyTable = Range("A2:C" & Cells(Rows.Count, "A").End(xlUp).Row).Value
    ReDim OutTable(1 To UBound(MyTable), 1 To 2)
    OutTable(1, 1) = "Customer"
    OutTable(1, 2) = "Top Reason"
    
    Cust = MyTable(1, 1)
    t = 1
    
    For i = 1 To UBound(MyTable)
        If MyTable(i, 1) <> Cust Then
            Call DoReason(MyTable, Cust, t, i - 1, ResultRow, OutTable)
            t = i
            Cust = MyTable(i, 1)
        End If
    Next i
    Call DoReason(MyTable, Cust, t, i - 1, ResultRow, OutTable)
    
    Range("E1:F" & UBound(MyTable)).Value = OutTable
    Application.ScreenUpdating = True
        
End Sub


Sub DoReason(MyTable, Cust, t, b, MyRow, OutTable)
Dim MyDict As Object, i As Long, d As String, w As Variant, m As Double, x As Variant, y As Double


    Set MyDict = CreateObject("Scripting.Dictionary")
    For i = t To b
        d = MyTable(i, 2)
        If MyDict.exists(d) Then
            w = Split(MyDict.Item(d), Chr(9))
            MyDict.Item(d) = CDbl(w(0)) + 100000 & Chr(9) & IIf(CDbl(MyTable(i, 3)) > CDbl(w(1)), CDbl(MyTable(i, 3)), w(1))
        Else
            MyDict.Add d, 100000 & Chr(9) & CDbl(MyTable(i, 3))
        End If
    Next i
    
    d = ""
    m = 0
    For Each x In MyDict
        w = Split(MyDict.Item(x), Chr(9))
        y = CDbl(w(0)) + CDbl(w(1))
        If y > m Then
            m = y
            d = x
        End If
    Next x
    
    OutTable(MyRow, 1) = Cust
    OutTable(MyRow, 2) = d
    MyRow = MyRow + 1
            
End Sub
 
Upvote 0
I made a few tweaks and just had to make sure the data set was sorted by customer number, then case reason, and time/date, but it's working quite well it seems. Many thanks!
 
Upvote 0

Forum statistics

Threads
1,224,827
Messages
6,181,194
Members
453,021
Latest member
pingpong7117

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