数组 CountIf 替换 - Count(Match())

Array CountIf Substitute - Count(Match())

核心问题

如何尽可能高效地(在性能方面)在一个范围内执行重复的 CountIf()s?


细节问题

范围到数组

由于每个 read/write 到电子表格都会导致 VBA 代码变慢,因此建议尽可能少地这样做。通常,如果某人重复 reading/writing 到一个范围,他或她应该先将该范围保存到一个数组,对数组执行操作,然后在必要时对电子表格进行最后的读取或写入。


示例值和代码

如何在上面的A2:A11范围内使用perform CountIf()s来计算每个值的个数并写入D2:D7?我希望下面的代码能够工作:

Sub M1ArrayCount()

Dim arrNumbers() As Variant
Dim Long1 As Long
Dim Loop1 As Long

arrNumbers() = ThisWorkbook.Sheets(1).Range("A2:A11").Value

With ThisWorkbook.Sheets(1)
    For Loop1 = 1 To 6
        .Cells(Loop1 + 1, 4).Value = Application.CountIf(arrNumbers(), Loop1)
    Next Loop1
End With

End Sub

CountIf() 不适用于数组

但是,因为 Application.CountIf() 只适用于范围而不适用于数组,所以 D2:D7 在 运行 上面的代码之后都显示 #VALUE! 错误。必须找到替代品。

解决方案 - 计数(匹配())

我们正在寻找的解决方案是:

Application.Count(Application.Match(SavedArray(), Array([lookup_value]), 0))


什么?这是如何运作的? --- 通常 return 行号的函数如何与数组配对并计算到 return 正确答案?如何计算行号?

机制说明

非常感谢@Jeeped,这是它的工作原理:

Match(lookup value, lookup array, 0) 的一个未记录的功能是,如果您将一个数组作为查找值,它将 Match() 您输入的数组中的每个值与查找数组相对应。因此,对于上面的例子,对于Loop = 1,它将变成:

{match(A2, Array("1"), 0),match(A3, Array("1"), 0), ... match(A11, Array("1"), 0)}

然后,根据@Jeeped:

Each match will either return a number or an error. The Count() function counts numbers, not errors. So you get a count of whether any of the values in A1:A11 match Loop1.

最终代码和值

Sub M1ArrayCount()

Dim arrNumbers() As Variant
Dim Long1 As Long
Dim Loop1 As Long

arrNumbers() = ThisWorkbook.Sheets(1).Range("A2:A11").Value

With ThisWorkbook.Sheets(1)
    For Loop1 = 1 To 6
        .Cells(Loop1 + 1, 4).Value = Application.Count(Application.Match(arrNumbers(), Array(Loop1), 0))
    Next Loop1
End With

End Sub


参考 ---

This answer

Question

Example:

myarray = array("First","Second","Second","Third","Fourth")

then what would the countif(myarray,"second") syntax be? (the result should equal 2 counts)

回答

Try also:

MsgBox Application.Count(Application.Match(myArray, Array("Second"), 0))

This chat

Dim rowin as integer 'this is a counter for the row index
For rowin = 2 To Sheets("Sheet1").UsedRange.Rows.Count
Sheets("Sheet1").Range("D" & rowin).Value = WorksheetFunction.CountIf(Range("A:A"), Range("C" & rowin))
Next