【问题标题】:Is OFFSET actually slow or just volatile?OFFSET 实际上是缓慢的还是不稳定的?
【发布时间】:2020-08-17 18:57:10
【问题描述】:

我在 Excel 中有一个表,它经常使用OFFSET 来获取相对于另一列的列。这是允许我动态调整表格大小的必要条件。

例如,在MyTable 的单元格D5 中,我有一个这样的公式 - 其中 D$2 是表格的第一行

=INDEX(
    OFFSET(
        D$2,
        0,
        (- OffsetDistance ),
        ROWS(
            MyTable
        )
    ),
    MATCH(
        LARGE(
            OFFSET(
                D$2,
                0,
                (- 1 ),
                ROWS(
                    MyTable
                )
            ),
            ROW() -
                ROW(
                    MyTable[#Headers]
                )
        ),
        OFFSET(
            D$2,
            0,
            (- 1 ),
            ROWS(
                MyTable
            )
        ),
        0
    )
)

现在我听说“OFFSET 很慢,因为它易变”。这就像说RAND() 很慢;生成随机数并不慢,与排序列表或搜索子字符串相比没有任何意义 - 缓慢是因为工作表经常重新计算。

我想知道,使用 OFFSET 函数比使用 Range 文字慢多少。基本上,我在灵活性和能够动态调整表格大小与更快的硬编码偏移之间进行权衡。

所以一般来说,OFFSET 本身是否可能是工作表中缓慢的根源?我想不会,因为我猜这是一个 O(1) 操作,只需将几个数字相加即可。但我想不出如何量化这个

【问题讨论】:

  • 我认为大 O 与 OFFSETRAND 的缓慢程度无关 - 在修改工作表中的任何单元格后,它们都必须重新计算 => 他们可以减慢插入新数据、更改自动过滤条件和其他看似无关的操作
  • 关键是,只要在工作表中计算任何内容,就会执行一个 volatile 函数。显然,您是执行一个这样的函数还是每行一个,以及您有 300 行还是 130 万行都存在差异。我建议您忽略警告,直到您觉得您的工作表反应迟缓。请记住,您最终可能会注意到的缓慢响应似乎与您怀疑的功能无关。 OFFSET() 本身很少会导致工作表计算。但是当其他事情发生时,它会重新计算。
  • OFFSET 本身非常快,其波动性可能是问题所在。我曾经用超过 10000 个 OFFSET 公式制作了一个工作簿,计算起来非常快。
  • 它们不应该——如果结果没有改变,则依赖项不应该重新计算(除非 Excel 的优化非常糟糕,可能是这种情况,但我希望不会)
  • @Aprillion 刚刚测试过,你所说的对于带有Application.Volatile 的 UDF 来说是 True,但它每次都返回相同的值,但奇怪的是 OFFSET 不是。

标签: excel performance excel-formula offset excel-2019


【解决方案1】:

由于 OFFSET(或其他不稳定的公式),速度将与重新计算的单元格数量成正比。由于它的波动性,它可能会变得非常缓慢。

几年前我停止使用 OFFSET,因为在使用许多公式时差异会变得很大。相反,我使用非易失性的 INDEX。

假设范围 A1:A100。假设我们想要从第 2 行开始的 50 个单元格。使用 OFFSET 将是:

=OFFSET(A1,1,0,50,1)

或者:

=OFFSET(A2,0,0,50,1)

相反,我可能会使用这个:

=A2:INDEX(A2:A101,50)

或者:

=INDEX(A1:A101,2):INDEX(A2:A101,51)

在这种情况下需要什么。


公式的复杂性也很重要。如果您将 INDEX 和 MATCH 等与 OFFSET 混合,然后将该公式拖动到 50000 行,那么这 50k 行将一直重新计算。也许您在 100000 行的表中进行匹配。我知道这有点牵强,但应避免使用易变的公式。

在 VBA 端,触发了 Worksheet_Calculate 事件,并且可能有基于该事件运行的代码。

【讨论】:

    猜你喜欢
    • 2023-03-09
    • 2017-06-01
    • 2016-10-10
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多