Excel multi-criteria CountIf for whole table - excel

I'm trying to count the number of occurrences in a table based on two criteria. The formula below seems to work when I change the second criteria range from F3:S7 to one column F3:F7. I tried to create a dim range and set the range for the are and sub it into the formula, but that doesn't work either. How can I get the second criteria to accept a range of several columns instead of one?
Sub Count_number_of_occurrences_with_multiple_criteria()
'declare a variable
Dim ws As Worksheet
Set ws = Worksheets("CountPrep2 (2)")
'count the number of occurrences with two criteria
ws.Range("B10") = Application.WorksheetFunction.CountIfs(ws.Range("B3:B7"), ws.Range("B9"), ws.Range("F3:S7"), ws.Range("A10"))
End Sub

According to the Microsoft documentation about CountIfs, each additional range must have the same number of rows and columns as Range1.
My suggestion would be to recreate the effect of checking the criteria using For Loops that cycle though the desired ranges. Like so:
Sub Count_number_of_occurrences_with_multiple_criteria()
'declare a variable
Dim ws As Worksheet, _
rng1 As Range, rng2 As Range, _
r1Cell As Range, r2Cell As Range, _
counter As Integer
Set ws = Worksheets("CountPrep2 (2)")
Set rng1 = ws.Range("B3:B7")
Set rng2 = ws.Range("F3:S7")
For Each r1Cell In rng1
If r1Cell = ws.Range("B9") Then
For Each r2Cell In rng2
If r2Cell = ws.Range("A10") Then
counter = counter + 1
End If
Next r2Cell
End If
Next r1Cell
'count the number of occurrences with two criteria
MsgBox counter
End Sub
Note: I don't know the specifics of your data or file format so the method by which I check the criteria likely does not accurately count the number of occurrences. This is just an example of how you might achieve your desired results.

Related

Can not SUM selected cells With SUMIF

I would like to be able to Check for criteria "owners" In column A and SUM cell from the same row column E with the cell above and repeat through the spread sheet where owner is found.
I have tried to use Function =SUMIF(A3,"*owner*",E2:E3) This returns the Value above the cell in the row with owner but does not SUM them.
I have also tried this VBA CODE and it does the same thing.
Sub vba_sumif()
Dim gRange As Range
Dim sRange As Range
Set gRange = Range("A3")
Set sRange = Range("E2:E3")
Range("G2") = _
WorksheetFunction.SumIf(gRange,"*Owner*", sRange)
End Sub
Ideally it would return the summed cells in the above cell. using VBA
Thanks again,
Aaron
Well first of all, I would suggest just using the formula unless you have a reason not to:
Formula:: Your first error with the formula is both ranges need to be the same size.
VBA:: Same thing here with range sizes, then you also need to remember to make sure Excel knows what sheet you're referring to. I like to do this with a With My_Worksheet_Namestatement, then include a . before any range from that sheet. Just make sure to change the sheet name to your sheet name
Option Explicit
Sub vba_sumif()
Dim TableSheet As Worksheet
Dim gRange As Range
Dim sRange As Range
Set TableSheet = Worksheets("TableSheet")
With TableSheet
Set gRange = .Range("A2:A13")
Set sRange = .Range("E2:E13")
.Range("G2").Value = _
WorksheetFunction.SumIf(gRange, "*Owner*", sRange)
End With
End Sub

SpecialCells(12).Value stops after first hidden row

I'm currently trying to copy a filtered column to an array to populate a ComboBox in a Powerpoint presentation.
The line of code I'm using to do this is:
ar = tbl.ListColumns(ColNumber).Range.SpecialCells(12).Value
Where "ar" is the destination array, "tbl" is the source table and "ColNumber" is the number of column I'm trying to copy.
The filtered column I'm trying to copy has around 180 records but I noticed the destination array has 6 values since it selected only until the first "hidden" row in the range, and skipped every other visible row after that.
Is there a way to get the value of every visible row and not just the first ones?
You are facing that issue because of Non Contigous range. You cannot use the method Array = Range.Value for Non Contigous range. There are two ways you can follow to achieve what you want.
WAY 1 Identify the Range, Loop through the cells and populate the array. Suitable for your case as you are dealing with single column.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim tbl As ListObject
Dim ar As Variant
Dim i As Long, n As Long, ColNumber As Long
Dim aCell As Range, rng As Range
'~~> Change this to the relevant sheet
Set ws = Sheet1
'~~> Change this to the relevant table
Set tbl = ws.ListObjects("Table1")
ws.AutoFilterMode = False
'~~> Change to relevant column number
ColNumber = 1
'~~> Autofilter as required
tbl.Range.AutoFilter Field:=ColNumber, Criteria1:="Blah1"
'~~> Set your range
Set rng = tbl.ListColumns(ColNumber).Range.SpecialCells(12)
'~~> Get the count of cells in that range
n = rng.Cells.Count
'~~> Resize the array to hold the data
ReDim ar(1 To n)
n = 1
'~~> Store the values from that range into the array
For Each aCell In rng.Cells
ar(n) = aCell.Value
n = n + 1
Next aCell
For i = LBound(ar) To UBound(ar)
Debug.Print ar(i)
Next i
End Sub
WAY 2 Identify the Range, loop thorough the Area and then loop through the cells in that Area and then populate the array. Very similar to the above code.
In Action

Divide a range of cells with a particular number if cell values are numeric

I have to divide all the cell values of sheet -"Databook" with a number 1000000 only if the cell contains numeric value. It means I have to divide only those cells in the sheet which contains numbers like 17577.2 , 2123, 13979123.22, 239812098321.1, and 9798.
Sub i()
'declare variables
Dim ws As Worksheet
Dim rng As Range
Dim myVal As Range
Set ws = Worksheets("Sheet1")
Set rng = ws.Range("A:Z")
For Each myVal In rng
If IsNumeric(myVal) = True Then
myVal = myVal.Value / 1000000
Else
Next myVal
End Sub
You currently suffer from a missing End If, thus your current code won't run at all. Properly indenting your code would have revealed the issue. I would also recommend not trying to loop all cells in your current range. Note that these are (for Excel 2019 at least) 27.262.976 cells to go through (you might want to first find your range of interest first; last used row, last used column). This many calls will be terribly slow. Limit that numbers by just using the actual numeric values at least.
Try to uitilize SpecialCells. The way it works > <YourRange>.SpecialCells(XlCellType, [XlSpecialCellsValue]). For example:
Sub Test()
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Sheet1")
For Each cl In ws.Range("A:Z").SpecialCells(2, 1)
cl.Value = cl.Value / 1000000
Next
End Sub
Where: .SpecialCells(2, 1) can also be read as .SpecialCells(xlCellTypeConstants, xlNumbers)
Note: If you have big chunks of cells that contain numeric values it might be beneficial to loop Areas property instead of Cells since you can load these into an array and perform calculations in memory before pasting back these values. This could also save you some valuable runtime.

VBA Macro autofilter for a range

I am trying to filter a set of data based a predetermined range of variables. These will be declared by the user of the spreadsheet in a set area of the "home" worksheet. However when running the macro it will return no results. I have attempted to resolve this in multiple ways however nothing has returned the desired results.
Up until now i have tried using operators, declaring the values as an array, filtering for the range of cells which will contain the values and also wildcards.
My current code is as below, neither of these return the output i would like
Dim fliterStr As Variant
filterStr = wsHome.Range("R6:R12").Value
wsMissing.Range("G1").AutoFilter field:=7, Criteria1:=filterStr
wsMissing.Range("G1").AutoFilter field:=7, Criteria1:="*X*", Operator:=xlFilterValues, Criteria2:="*Y*"
the expected results would be the filter searching for any values matching the variables in the range of R6:R12, however currently this is returning as blank.
the second piece of code returns some but not all of the desired results. if i exclude the operator and Criteria2 then i see a different set of results that should be included but arent.
The array for AutoFIlter criteria works for a 1-D array. When you pickup a chunk of a column, you are creating a 2-D array. You need to use TRANSPOSE() to convert it.
Say we have in Sheet1:
and in Sheet2:
Running:
Sub AutoDemo()
Dim wsHome As Worksheet, wsMissing As Worksheet
Dim rng1 As Range, rng2 As Range, wf As WorksheetFunction
Dim filterStr
Set wsHome = Sheets("Sheet1")
Set wsMissing = Sheets("Sheet2")
Set wf = Application.WorksheetFunction
Set rng1 = wsHome.Range("A1:G20")
Set rng2 = wsMissing.Range("R6:R12")
filterStr = wf.Transpose(rng2)
rng1.AutoFilter Field:=7, Criteria1:=filterStr, Operator:=xlFilterValues
End Sub
will produce:
It is TRANSPOSE() that makes the 1-D array.

Maximum of Multiple Named Ranges

I am having a lot of trouble with this one. I want to replicate this value in VBA:
=MAX(MAX(Named_Range1),MAX(Named_Range2),MAX(Named_Range3))
I am having an impossible time trying to get this done.
If the three ranges are in the same sheet then:
Sub MaxMax()
Dim r As Range
Set r = Union(Range(Named_Range1), Range(Named_Range2), Range(Named_Range3))
MsgBox Application.WorksheetFunction.Max(r)
End Sub
If you don't want to place the formula in one of the cells and calculate the result in VBA code, you can also use the following code:
Dim rng1 As Range, rng2 As Range, rng3 As Range
Dim y As Double
Set rng1 = ThisWorkbook.Names("Named_Range1").RefersToRange
Set rng2 = ThisWorkbook.Names("Named_Range2").RefersToRange
Set rng3 = ThisWorkbook.Names("Named_Range3").RefersToRange
y = WorksheetFunction.Max(rng1, rng2, rng3)
If named ranges are in another workbook, replace ThisWorkbook with Workbooks("workbook name")
For the result to be placed in F9, please try:
Sub Maximal()
Range("F9").Formula = "=MAX(MAX(Named_Range1),MAX(Named_Range2),MAX(Named_Range3))"
End Sub

Resources