“It’s not what you look at that matters, it’s what you see.” [Henry David Thoreau]

Note: Please notice that Excel 365 Insider now offers two similar but more powerful worksheet functions than sbMiniPivot - GROUPBY and PIVOTBY. Once your Excel can use these functions, my UDF sbMiniPivot should only be used for VBA training purposes.

Abstract

If you want to apply a function like CAT, COUNT, MAX, MIN or SUM on a list of given number or string combinations with a condition applied, you can use sbMiniPivot.

sbMiniPivot

Name

sbMiniPivot - Concatenate, count, sum or return min or max of last given input column for all combinations of the previous ones where same row of condition column is True

Synopsis

sbMiniPivot(sFunction, vCondition, ParamArray vInput)

Description

sbMiniPivot performs the function sFunction on last given column of vInput for all combinations of the previous ones where corresponding elements of vCondition are True. It returns a variant array.

Options

sFunction - Specifies the function which has to be applied to the combinations. Can be concatenate (cat), count, max(imum), min(imum), sum

vCondition - Condition constant True or False or column which needs to contain True/False values

vInput - Two or more columns. sFunction will be applied on last input column for all combinations of the previous ones where same row of condition column is True

Appendix – sbMiniPivot Code

Please read my Disclaimer.

Option Explicit
    
Enum mc_Macro_Categories
    mcFinancial = 1
    mcDate_and_Time
    mcMath_and_Trig
    mcStatistical
    mcLookup_and_Reference
    mcDatabase
    mcText
    mcLogical
    mcInformation
    mcCommands
    mcCustomizing
    mcMacro_Control
    mcDDE_External
    mcUser_Defined
    mcFirst_custom_category
    mcSecond_custom_category 'and so on
End Enum 'mc_Macro_Categories

Function sbMiniPivot(sFunction As String, _
         vCondition As Variant, _
         ParamArray vInput() As Variant) As Variant
'sbMiniPivot performs the function sFunction on last given column of
'vInput() for all combinations of the previous ones where corresponding
'elements of vCondition are TRUE.
'Example:
'    A     B     C
' 1 Smith Adam   1
' 2 Myer  Ben    3
' 3 Smith Ben    2
' 4 Smith Adam   7
' 5 Myer  Ben    4
'Now array-enter into D1
'=sbMiniPivot("sum", B1:B5="Ben", A1:A5,B1:B5,C1:C5) and you will get
'    D      E    F
' 1 Myer   Ben   7
' 2 Smith  Ben   2
'Source (EN): http://www.sulprobil.de/sbminipivot_en/
'Source (DE): http://www.berndplumhoff.de/sbminipivot_de/
'(C) (P) by Bernd Plumhoff 31-Jul-2022 PB V1.1
Dim b As Boolean, bCondition As Boolean
Dim i As Long, j As Long, k As Long, liscount As Long
Dim lvdim As Long, lcdim As Long
Dim obj As Object
Dim s As String, sC As String
Dim vR As Variant

With Application.WorksheetFunction
sC = "|"
k = 0
vInput(0) = .Transpose(.Transpose(vInput(0)))
If LCase(sFunction) = "count" Then liscount = 1
If UBound(vInput) < 1 - liscount Then
   sbMiniPivot = CVErr(xlErrValue)
   Exit Function
End If
lvdim = UBound(vInput(0))
Select Case VarType(vCondition)
Case vbBoolean
    bCondition = True
Case vbArray + vbVariant
    bCondition = False
    vCondition = .Transpose(.Transpose(vCondition))
    lcdim = UBound(vCondition, 1)
    If lcdim <> lvdim Then
       sbMiniPivot = CVErr(xlErrRef)
       Exit Function
    End If
Case Else
   sbMiniPivot = CVErr(xlErrNA)
   Exit Function
End Select
If lvdim > 100 Then lvdim = 100 'Let us start with small dimension
On Error GoTo ErrHdl
ReDim vR(0 To UBound(vInput) + liscount, 1 To lvdim)
For j = 1 To UBound(vInput)
   vInput(j) = .Transpose(.Transpose(vInput(j)))
   If UBound(vInput(0)) <> UBound(vInput(j)) Then
       sbMiniPivot = CVErr(xlErrRef)
       Exit Function
   End If
Next j
Set obj = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(vInput(0))
    b = bCondition
    If Not b Then b = vCondition(i, 1)
    If b Then
        s = vInput(0)(i, 1)
        For j = 1 To UBound(vInput) - 1 + liscount
            s = s & sC & vInput(j)(i, 1)
        Next j
        If obj.Item(s) > 0 Then
            Select Case LCase(sFunction)
            Case "cat", "concatenate"
                vR(UBound(vInput), obj.Item(s)) = vR(UBound(vInput), _
                    obj.Item(s)) & "," & vInput(UBound(vInput))(i, 1)
            Case "count"
                vR(UBound(vInput) + 1, obj.Item(s)) = vR(UBound(vInput) + 1, _
                    obj.Item(s)) + 1
            Case "max", "maximum"
                If vR(UBound(vInput), obj.Item(s)) < vInput(UBound(vInput))(i, 1) Then
                    vR(UBound(vInput), obj.Item(s)) = vInput(UBound(vInput))(i, 1)
                End If
            Case "min", "minimum"
                If vR(UBound(vInput), obj.Item(s)) > vInput(UBound(vInput))(i, 1) Then
                    vR(UBound(vInput), obj.Item(s)) = vInput(UBound(vInput))(i, 1)
                End If
            Case "sum"
                vR(UBound(vInput), obj.Item(s)) = vR(UBound(vInput), _
                    obj.Item(s)) + vInput(UBound(vInput))(i, 1)
            Case Else
                sbMiniPivot = CVErr(xlErrRef)
            End Select
        Else
            k = k + 1
            obj.Item(s) = k
            For j = 0 To UBound(vInput)
                vR(j, k) = vInput(j)(i, 1)
            Next j
            If liscount = 1 Then vR(UBound(vInput) + 1, k) = 1
        End If
    End If
Next i
'Reduce result array to used area
If k > 0 Then ReDim Preserve vR(0 To UBound(vInput) + liscount, 1 To k)
sbMiniPivot = .Transpose(vR)
Set obj = Nothing
End With
Exit Function

ErrHdl:
If Err.Number = 9 Then
   If i > lvdim Then
       'Here we normally get if we breach Ubound(vR,2)
       'So we need to increase last dimension
       lvdim = 10 * lvdim
       If lvdim > UBound(vInput(0)) Then lvdim = UBound(vInput(0))
       ReDim Preserve vR(0 To UBound(vInput) + liscount, 1 To lvdim)
       Resume 'Back to statement which caused error
   End If
End If
'Other error - terminate
On Error GoTo 0
Resume
End Function

Sub DescribeFunction_sbMiniPivot()
'Run this only once, then you will see this description in the function menu
Dim FuncName As String, FuncDesc As String, Category As String
Dim ArgDesc(1 To 3) As String
FuncName = "sbMiniPivot"
FuncDesc = "Concatenate, count, sum or return min or max of last given input " & _
    "column for all combinations of the previous ones where same row " & _
    "of condition column is True"
Category = mcStatistical
ArgDesc(1) = "Function to apply - cat, count, max, min, or sum"
ArgDesc(2) = "Condition constant True or False or column which contains True/False values"
ArgDesc(3) = "Two or more columns"
Application.MacroOptions _
    Macro:=FuncName, _
    Description:=FuncDesc, _
    Category:=Category, _
    ArgumentDescriptions:=ArgDesc
End Sub

Download

Please read my Disclaimer.

sbMiniPivot.xlsm [41 KB Excel file, open and use at your own risk]