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:
Ooh that's better and really quick, thanks for all your help with this :)
 
Upvote 0

Excel Facts

Get help while writing formula
Click the italics "fx" icon to the left of the formula bar to open the Functions Arguments dialog. Help is displayed for each argument.
Hi WBD,
I have developed my spsht further over the weekend and wanted to ask for a bit more adjustment to your coding if possible?
Originally I was just interrogating averages on one wksheet (Data) but now need to count averages on 10 wkshts (named 1,2,3..10) and deposit the average counts into 10 sets of buckets all in the Report wksht. The buckets best sitting below one another, so the results from wksht '1' would sit in $N$17:$Q$17 and wksht '2' $N$18:$Q$18 and so on. The header criteria would be the same for all. Is this achievable??
I was going to generate 10 separate copies of your existing code but thought there may be a better more efficient option using one code.
Appreciate your time if you're able to assist further.
Rgds,
 
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 on the Report sheet
Public Sub WBD20170821()

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
Dim dataSheet As Long

' Find the report sheet
Set wsReport = Worksheets("Report")

' Process all data sheets
For dataSheet = 1 To 10
    ' Find the data sheet
    Set wsData = Nothing
    On Error Resume Next
    Set wsData = Worksheets(CStr(dataSheet))
    On Error GoTo 0
    
    ' Did we find the sheet
    If Not wsData Is Nothing Then
        ' Clear out the buckets
        For thisCol = 0 To 3
            buckets(thisCol) = 0
        Next thisCol
        
        ' 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
            
            ' 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
        Next thisRow
        
        ' Now populate the totals into the table
        For thisCol = 0 To 3
            wsReport.Range(BUCKET_RANGE).Offset(dataSheet - 1)(thisCol + 1).Value = buckets(thisCol)
        Next
    End If
Next dataSheet

End Sub

WBD
 
Upvote 0
Using Formula and without helper column,


Unknown
ABCDEFGHIJKLMN
1
2Header1Header2Header3Header4Header5Header6Header7Header8Header9Header10
395105224974
4391056531054
567141094874Include Headers in the average
610615888693Header1
794591136101Header2
81618238848Header6
97548862821
1062553910866
11510631098118
1213166993910
13310101214629
14293610125106
154483177346
16438936103109
176313526696AveragesResult (Count)
186762521109768
1948588146364.519
206685372766328
2161042172311031
22109447510557
2317292219105
24594716310103
2510152145473
261387611759
27310188424106
28521768491010
2952105333128
306559923477
31811073105651
Sheet6
Cell Formulas
RangeFormula
N18{=SUM(IF((MMULT(IF(ISNUMBER(MATCH($A$2:$J$2,$M$6:$M$15,0)),($A$3:$J$3)^0,0),TRANSPOSE($A$3:$J$31))/COUNTA($M$6:$M$15))>M18,1,0))}
N21{=SUM(IF((MMULT(IF(ISNUMBER(MATCH($A$2:$J$2,$M$6:$M$15,0)),($A$3:$J$3)^0,0),TRANSPOSE($A$3:$J$31))/COUNTA($M$6:$M$15))<=M21,1,0))}
Press CTRL+SHIFT+ENTER to enter array formulas.
 
Last edited:
Upvote 0
Hi WBD,
Me again but hopefully the last query on this one!
I wanted to substitute the bucket criteria with references to values in cells so I changed the following:
Case Is > 6
to
Case Is > Range ("N10")
but it won't play, what would be the correct code for this? N10 will obviously contain the number 6
Cheers.
 
Upvote 0
Hi,
it doesn't seem to like that - Run Time Error 16 - Expression too complex.
 
Upvote 0
OK. Then perhaps this:

Code:
            ' Decide which bucket to put the row in
            If rowAverage > wsReport.Range("N10").Value Then
                    buckets(0) = buckets(0) + 1
            ElseIf rowAverage > wsReport.Range("O10").Value Then
                    buckets(1) = buckets(1) + 1
            ElseIf rowAverage > wsReport.Range("P10").Value Then
                    buckets(2) = buckets(2) + 1
            Else
                    buckets(3) = buckets(3) + 1
            End If

WBD
 
Upvote 0

Forum statistics

Threads
1,224,828
Messages
6,181,214
Members
453,024
Latest member
Wingit77

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