【问题标题】:Optimizing Excel CountIfs - can I make it go faster?优化 Excel CountIfs - 我可以让它更快吗?
【发布时间】:2021-08-24 01:01:20
【问题描述】:

我有一些较大的文件需要验证其中的数据。其中大部分是自动输入的,可以自动输入我需要的公式。这有助于消除在大文件上复制和粘贴的错误。问题在于这个最新的验证。

最新的验证之一涉及计算匹配 3 列的行数。 3 列在工作表 2 中,要计数的行在工作表 1 中。然后将此计数与基于工作表 2 的预期数字进行比较。使用 CountIF 很容易,但文件很大,最多可能需要其中一些是一个小时。我正在努力寻找更快的东西。

我正在使用较小的文件,但仍需要大约 1 分钟。只有大约 1800 行。

我有这样的事情:

在 Check1 中我使用的是:=COUNTIFS(Sheet1!A:A,A2,Sheet1!B:B,B2,Sheet1!C:C,C2)

我的代码将该公式放在活动单元格中。有没有更好的方法来做到这一点?

无论如何 - 使用 VB 或任何东西 - 来提高性能。 当行开始进入 10 的数千时,是时候开始这个并吃午饭了。然后,希望当我回到办公桌时完成!

谢谢。

【问题讨论】:

  • 请出示代码。导致延迟的不是公式。
  • 我认为他此时只是在使用countifs函数。
  • ActiveCell.Offset(0,6).FormulaR1C1 = "COUNTIFS(...." 也试过 ActiveCell.Offset(0,6).Value = "COUNTIFS(..."
  • 我们需要查看完整的循环,问题在于您使用的是 select 和 activecell。
  • 您是否使用 VBA 将此公式写入每一行?那会很慢。把公式写一次,然后抄下来。

标签: excel vba


【解决方案1】:

您基本上必须遍历每一列的所有行,这很昂贵。您也许可以将其拆分为两个任务:

  1. 将列 A-C 合并为一个值 =CONCAT(A2,B2,C2)
  2. 然后在此列上仅执行一次计数=COUNTIF(D:D,D2)

这样你就可以以新的 concat 为代价摆脱两个(时间)昂贵的计数。

【讨论】:

  • Countifs 的时间并不昂贵。它非常快。 VBA 循环中更有可能出现延迟。
【解决方案2】:

您应该将 CountIf 作用于整个列的范围缩小到实际使用的范围

你的代码可以写公式的结果而不是公式本身

如下:

With Sheet1
    Set sheet1Rng = Intersect(.UsedRange, .Range("A:C"))
End With

With Sheet2
    For Each cell in Intersect(.UsedRange, .Range("A:A"))
        cell.Offset(,3) = WorksheetFunction.CountIfs(sheet1Rng.Columns(1), cell.Value, sheet1Rng.Columns(2), cell.Offset(,1).Value, sheet1Rng.Columns(3),cell.Offset(2).Value)
    Next cell
End With

【讨论】:

    【解决方案3】:

    我设置了一个模拟表,使用与您显示的类似的布局,有 10,000 行,并使用您显示的 COUNTIFS 公式手动填充它。更改数据中的单个项目会触发重新计算,大约需要十秒钟左右的时间才能执行。

    然后我尝试了以下宏,它在不到一秒的时间内执行。所有的计数都是在 VBA 宏中完成的。所以这个 Dictionary 方法或许可以解决你的速度问题。

    在运行此之前,如果工作表上有 COUNTIFS,您可能需要将计算状态设置为手动(或在代码中进行)。


    Option Explicit
    'set reference to Microsoft Scripting Runtime
    
    Sub CountCol123()
        Dim DCT As Dictionary
        Dim V As Variant
        Dim WS As Worksheet, R As Range
        Dim I As Long
        Dim sKey As String
    
    Set WS = Worksheets("sheet2")
    
    'read the info into an array
    With WS
        Set R = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=4)
        V = R
    End With
    
    'Get count of the matches
    Set DCT = New Dictionary
    For I = 2 To UBound(V, 1)
        sKey = V(I, 1) & "|" & V(I, 2) & "|" & V(I, 3)
        If DCT.Exists(sKey) Then
            DCT(sKey) = DCT(sKey) + 1
        Else
            DCT.Add Key:=sKey, Item:=1
        End If
    Next I
    
    'Get the results and write them out
    For I = 2 To UBound(V, 1)
        sKey = V(I, 1) & "|" & V(I, 2) & "|" & V(I, 3)
        V(I, 4) = DCT(sKey)
    Next I
    
    'If you have COUNTIFS on the worksheet when testing this,
    ' or any other formulas that will be triggered,
    ' then uncomment the next line
    'Application.Calculation = xlCalculationManual
    
    With R
        .EntireColumn.Clear
        .Value = V
    End With
    
    End Sub
    

    【讨论】:

      【解决方案4】:

      Hancom Office 2020 中名为 Cell 的 Excel 替代品在计数方面非常快。不知道为什么。在我的 i7-5775C 上,Excel 2019 的计数需要 90 秒,其中有两个条件来填充 10,000 行结果。使用 Cell,完全相同的操作在 28 秒内完成。我已验证结果与 Excel 2019 生成的结果相符。

      【讨论】:

        猜你喜欢
        • 2022-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-06
        • 1970-01-01
        • 2019-04-28
        • 1970-01-01
        相关资源
        最近更新 更多