有一个更快的CountIF

正如标题所说。 是否有任何函数或VBA代码与countif具有相同的function,速度要快很多。 目前在大规模countif中,它只是吃掉我的CPU。

这只是工作表中的一个基本countif。 不在VBA中。 =countif(X:X,Y)然而,这些名单是巨大的。 所以这两个列表都是大约10万行

如果你可以没有计数的事件发生,只是希望检查是否在y列中存在x值,那么用ISNUMBER函数返回布尔值TRUE或FALSE来评估MATCH函数查找将大大加快处理速度。

 =ISNUMBER(MATCH(S1, Y:Y, 0)) 

填写必要的所有回报。 对返回的值进行sorting和/或过滤以将结果制成表格。

附录:

显然是有的。 MATCH函数在COUNTIF 函数计算时间上的巨大改进使我怀疑MATCH是否不能放入循环中,将lookup_array参数中的第一个单元前进到之前返回的行号加1,直到没有更多匹配。 此外,随后的MATCH调用查找相同的数字(增加计数),可以通过调整(缩小)列的高度以及返回的行号来使lookup_array单元格范围更小。 如果已处理的值及其计数已存储为脚本字典中的键和项,则可以立即parsing重复值而不处理计数。

 Sub formula_countif_test() Dim tmr As Double appOFF tmr = Timer With Sheet2.Cells(1, 1).CurrentRegion With .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count) 'skip header .Cells(1, 3).Resize(.Rows.Count, 1).FormulaR1C1 = _ "=countif(c1, rc2)" 'no need for calculate when blocking in formulas like this End With End With Debug.Print "COUNTIF formula: " & Timer - tmr appON End Sub Sub formula_match_test() Dim rw As Long, mrw As Long, tmr As Double, vKEY As Variant 'the following requires Tools, References, Microsoft Scripting Dictionary Dim dVALs As New Scripting.dictionary dVALs.CompareMode = vbBinaryCompare 'vbtextcompare for non-case sensitive appOFF tmr = Timer With Sheet2.Cells(1, 1).CurrentRegion With .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count) 'skip header For rw = 1 To .Rows.Count vKEY = .Cells(rw, 2).Value2 If Not dVALs.Exists(vKEY) Then dVALs.Add Key:=vKEY, _ Item:=Abs(IsNumeric(Application.Match(vKEY, .Columns(1), 0))) If CBool(dVALs.Item(vKEY)) Then mrw = 0: dVALs.Item(vKEY) = 0 Do While IsNumeric(Application.Match(vKEY, .Columns(1).Offset(mrw, 0).Resize(.Rows.Count - mrw + 1, 1), 0)) mrw = mrw + Application.Match(vKEY, .Columns(1).Offset(mrw, 0).Resize(.Rows.Count - mrw + 1, 1), 0) dVALs.Item(vKEY) = CLng(dVALs.Item(vKEY)) + 1 Loop End If .Cells(rw, 3) = CLng(dVALs.Item(vKEY)) Else .Cells(rw, 3) = CLng(dVALs.Item(vKEY)) End If Next rw End With End With Debug.Print "MATCH formula: " & Timer - tmr dVALs.RemoveAll: Set dVALs = Nothing appON End Sub Sub appON(Optional ws As Worksheet) Application.ScreenUpdating = True Application.EnableEvents = True Application.Calculation = xlCalculationAutomatic End Sub Sub appOFF(Optional ws As Worksheet) Application.ScreenUpdating = False Application.EnableEvents = False Application.Calculation = xlCalculationManual End Sub 

MATCH_COUNTIF的示例数据

我使用了10K行,列A和B由RANDBETWEEN(1, 999)填充RANDBETWEEN(1, 999)然后复制并粘贴为值。

已用时间:

testing1 1 – 10K行×2列填充RANDBETWEEN(1 999)
COUNTIF公式:15.488秒
MATCH公式:1.592秒

testing2² – 10K行×2列填充RANDBETWEEN(1,99999)
COUNTIF公式:14.722秒
MATCH公式:3.484秒

我还将COUNTIF公式中的值复制到另一列,并将它们与编码的MATCH函数返回的值进行比较。 他们在10K行是相同的。
¹ 更多的倍数; less零计数
² 更多的零计数,更less的倍数

虽然数据的性质明显地产生了显着的差异,但编码的MATCH函数每次都优于本地COUNTIF工作表函数。

不要忘记VBE的工具►参考文献►Microsoft Scripting Dictionary。