Formula using averageifs & countifs with multiple criteria

cjcass

Well-known Member
Joined
Oct 27, 2011
Messages
683
Office Version
  1. 2016
Platform
  1. Windows
Hi,

I’m looking for a solution that can count the number of times averages occur in a table based on several criteria. Looking at the picture below, I’m trying to work out a formula that can go into cells N17:N20 that will calculate the count of averages that meet the variable criteria in the yellow cells (M5:M14 & M17:M20). I have highlighted the results that the formula would give for averages >6 and <=3 so you can visualise the solution.

Points to note are:
1. The number of rows in the table will be 50,000
2. The signs (“<” etc.) don’t need to be typed next to the numbers as displayed in M17:M20
3. I don’t want to use any helper columns in the solution

Hope you may be able to help, many thanks.
255m9g5.jpg
[/IMG]
 
Last edited:

Excel Facts

Fastest way to copy a worksheet?
Hold down the Ctrl key while dragging tab for Sheet1 to the right. Excel will make a copy of the worksheet.
The only way I could come up with using formulas requires a helper column:


Excel 2016 (Windows) 32 bit
ABCDEFGHIJKLMN
1Header1Header2Header3Header4Header5Header6Header7Header8Header9Header10
2951052249745.33
33910565310545.67
4671410948747.33Include Headers in the average
5106158886938.00Header1
6945911361014.67Header2
716182388483.33Header6
875488628216.00
9625539108665.67
105106310981188.00
11131669939104.33
123101012146294.67
132936101251064.00
1444831773465.00
154389361031094.33
1663135266963.67AveragesResult (Count)
17676252110975.00>68
1848588146364.33>4.519
1966853727666.33>328
206104217231107.67<=31
211094475105578.00
22172922191053.33
235947163101036.67
24101521454735.00
2513876117591.67
263101884241065.67
275217684910105.00
28521053331283.33
2965599234774.33
308110731056516.33
Sheet1
Cell Formulas
RangeFormula
K2=SUMPRODUCT(($A2:$J2)*(--ISNUMBER(MATCH($A$1:$J$1,$M$5:$M$14,0))))/COUNTA($M$5:$M$14)
N17=COUNTIFS($K$2:$K$30,">6")
N18=COUNTIFS($K$2:$K$30,">4.5")
N19=COUNTIFS($K$2:$K$30,">3")
N20=COUNTIFS($K$2:$K$30,"<=3")


You can always hide column K or put it out of sight to the right ...

WBD
 
Last edited:
Upvote 0
Hi,
Thanks for your solution I'll keep it in reserve if I can't find one without a helper column. These tables will be appearing on 50 different worksheets and I was hoping to keep them free from formulas hence hoping for a solution without helpers.
 
Upvote 0
maybe a solution using vba if a formula without a helper column is not achievable?
 
Upvote 0
This will do it for the current sheet:

Code:
Public Sub WBD20170817()

Dim lastRow As Long
Dim lastCol As Long
Dim thisRow As Long
Dim thisCol As Long
Dim buckets(3) As Long
Dim headerCount As Long
Dim rowAverage As Double

' Find the last row of data
lastRow = Cells(Rows.Count, 1).End(xlUp).Row

' Find the last column
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column

' Work through all rows
For thisRow = 2 To lastRow
    ' Reset the average for this row and the number of headers matched
    rowAverage = 0
    headerCount = 0
    
    ' Process all columns on this row
    For thisCol = 1 To lastCol
        ' Is the header on this column in the list of headers?
        If Not IsError(Application.Match(Cells(1, thisCol).Value, Range("$M$5:$M$14"), 0)) Then
            ' Yes it is - accumulate this value and add 1 to the header count
            headerCount = headerCount + 1
            rowAverage = rowAverage + Cells(thisRow, thisCol).Value
        End If
    Next thisCol
    
    ' Divide the total by the number of headers
    rowAverage = rowAverage / headerCount
    
    ' Decide which bucket to put the row in
    buckets(0) = buckets(0) + IIf(rowAverage > 6, 1, 0)
    buckets(1) = buckets(1) + IIf(rowAverage > 4.5, 1, 0)
    buckets(2) = buckets(2) + IIf(rowAverage > 3, 1, 0)
    buckets(3) = buckets(3) + IIf(rowAverage <= 3, 1, 0)
Next thisRow

' Now populate the totals into the table
For thisRow = 0 To 3
    Cells(thisRow + 17, "N").Value = buckets(thisRow)
Next

End Sub

WBD
 
Upvote 0
Hi WBD,

Thanks for this it works great. Have a few questions re. tweaking this code if I may:

1. If my table headers drop down to Row 4 (so I can add some other info above the table) how would I change the code?
2. How would I tweak the criteria in the buckets to add an 'And', so for example bucket (1) reads if the row average is >4.5 and <6?
3. How would I change the code if I wanted the buckets to populate cells across the row (N17:Q17) as opposed to down the column (N17:N20)?
4. My criteria cells and the buckets will be located in a worksheet called 'Report' whereas the table of data will be located in a sheet called 'Data', how would this be coded?

Many thanks for all your help
 
Upvote 0
Code:
Private Const HEADER_ROW = 4 ' Set to be the row that contains the headers on the Data sheet
Private Const CRITERIA_RANGE = "$M$5:$M$14" ' Set to be the range that contains the criteria on the Report sheet
Private Const BUCKET_RANGE = "$N$17:$Q$17" ' Set to be the range where we will put the values
Public Sub WBD20170818()

Dim lastRow As Long
Dim lastCol As Long
Dim thisRow As Long
Dim thisCol As Long
Dim buckets(3) As Long
Dim headerCount As Long
Dim rowAverage As Double
Dim wsReport As Worksheet
Dim wsData As Worksheet

' Find the sheets
Set wsReport = Worksheets("Report")
Set wsData = Worksheets("Data")

' Find the last row of data
lastRow = wsData.Cells(wsData.Rows.Count, 1).End(xlUp).Row

' Find the last column
lastCol = wsData.Cells(HEADER_ROW, wsData.Columns.Count).End(xlToLeft).Column

' Work through all rows
For thisRow = HEADER_ROW + 1 To lastRow
    ' Reset the average for this row and the number of headers matched
    rowAverage = 0
    headerCount = 0
    
    ' Process all columns on this row
    For thisCol = 1 To lastCol
        ' Is the header on this column in the list of headers?
        If Not IsError(Application.Match(wsData.Cells(HEADER_ROW, thisCol).Value, wsReport.Range(CRITERIA_RANGE), 0)) Then
            ' Yes it is - accumulate this value and add 1 to the header count
            headerCount = headerCount + 1
            rowAverage = rowAverage + wsData.Cells(thisRow, thisCol).Value
        End If
    Next thisCol
    
    ' Divide the total by the number of headers
    rowAverage = rowAverage / headerCount
    wsData.Cells(thisRow, thisCol).Value = rowAverage
    
    ' Decide which bucket to put the row in
    If rowAverage > 6 Then buckets(0) = buckets(0) + 1
    If rowAverage > 4.5 And rowAverage <= 6 Then buckets(1) = buckets(1) + 1
    If rowAverage > 3 And rowAverage <= 4.5 Then buckets(2) = buckets(2) + 1
    If rowAverage <= 3 Then buckets(3) = buckets(3) + 1
Next thisRow

' Now populate the totals into the table
For thisCol = 0 To 3
    wsReport.Range(BUCKET_RANGE)(thisCol + 1).Value = buckets(thisCol)
Next

End Sub

I think that should answer everything. If the buckets are exclusive then you could replace this:
Code:
    ' Decide which bucket to put the row in
    If rowAverage > 6 Then buckets(0) = buckets(0) + 1
    If rowAverage > 4.5 And rowAverage <= 6 Then buckets(1) = buckets(1) + 1
    If rowAverage > 3 And rowAverage <= 4.5 Then buckets(2) = buckets(2) + 1
    If rowAverage <= 3 Then buckets(3) = buckets(3) + 1

with this:
Code:
    ' Decide which bucket to put the row in
    Select Case rowAverage
        Case Is > 6
            buckets(0) = buckets(0) + 1
        Case Is > 4.5
            buckets(1) = buckets(1) + 1
        Case Is > 3
            buckets(2) = buckets(2) + 1
        Case Else
            buckets(3) = buckets(3) + 1
    End Select

WBD
 
Upvote 0
Hi,
Thanks for this, one thing though - when I run the code after I've changed the header criteria the cells in column N on the Data sheet are populated with the averages down all the rows in the table - not sure if that's meant to happen? if it is it's a slow population of data.
Rgds,
 
Upvote 0
Oops. That was a line of debugging I put in. Please remove this line:

Code:
    wsData.Cells(thisRow, thisCol).Value = rowAverage

WBD
 
Upvote 0

Forum statistics

Threads
1,223,911
Messages
6,175,325
Members
452,635
Latest member
laura12345

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