【问题标题】:ROW() function behaves differently inside SUM() and SUMPRODUCT()ROW() 函数在 SUM() 和 SUMPRODUCT() 中的行为不同
【发布时间】:2012-06-20 16:40:51
【问题描述】:

问题定义:

在单元格A1 中输入任意数字。现在在第一行的任意位置尝试以下公式。

=SUM(INDIRECT("A"&ROW()))

=SUMPRODUCT(INDIRECT("A"&ROW()))

第一个公式计算,第二个给出#VALUE 错误。 这是由ROW() 函数在SUMPRODUCT() 内部的行为不同引起的。

在第一个公式中,ROW() 返回1。在第二个公式中,行返回 {1}(一个长度的数组),即使该公式尚未作为 CSE 公式输入。

为什么会这样?

背景

我需要评估类型的公式

=SUMPRODUCT(INDIRECT(*range formed by concatenation and using ROW()*)>1)

这是一个错误。作为此问题的解决方法,我现在在另一个单元格中计算ROW()(显然在同一行中)并将其连接到我的INDIRECT() 中。或者,我也尝试将其封装在 sum 函数中,例如 SUM(ROW()),并且效果也很好。

如果有人可以解释(或指向可以解释的资源)为什么 ROW() 在没有输入 CSE 的情况下返回 SUMPRODUCT() 内的数组,我将不胜感激。

【问题讨论】:

    标签: excel excel-2007 excel-formula excel-2003


    【解决方案1】:

    有趣的问题。这里有一些我没有看到记录的微妙问题。

    INDIRECT("A"&ROW()) 似乎返回了一个数组,该数组由一个元素组成,该元素是对单元格的引用,而不是该单元格中的值。许多函数无法正确解析这种类型的数据,但少数函数(如 N 和 T)可以“取消引用”数组并返回基础值。

    以数组中有两个元素的情况为例:

    =SUM(N(INDIRECT("A"&ROW(1:2))))
    

    输入数组时返回A1+A2,正常输入时只返回A1。但是,在此公式中将 ROW(1:2) 更改为 {1;2} 会在正常输入时返回正确的结果。无论是否输入数组,等效的 SUMPRODUCT 公式都会返回 A1+A2。

    这可能与参数在函数中的注册方式有关。根据http://msdn.microsoft.com/en-us/library/bb687900.aspx,基本上有两种方法可以注册函数参数来处理 Excel 数据类型:

    类型 R/U:“值、数组和范围引用。”

    类型 P/Q:“在准备这些参数时,Excel 将单单元格引用转换为简单值,将多单元格引用转换为数组。”

    SUM 参数似乎符合 R/U 类型,而 SUMPRODUCT 参数的行为类似于 P/Q 类型。数组输入上面的 SUM 公式会强制将 ROW 中的范围引用参数作为数组进行评估,而 SUMPRODUCT 会自动发生这种情况。

    更新

    经过更多调查,这里有可能支持这一理论的进一步证据。根据评论中的链接,公式 =SUM((A1,A2)) 给出的值与以下相同:

    ?executeexcel4macro("CALL(""Xlcall32"",""Excel4"",""2JRJR"",4,,1,(!R1C1,!R2C1))")
    

    通过将 2JRJR 更改为 2JRJP 将最后一个参数注册为类型 P 在这种情况下会出错,但确实允许像 !R1C1:!R2C1 这样的单个区域范围。另一方面,将 4 (xlfsum) 更改为 228 (xlfsumproduct) 只允许单个区域引用,就像 SUMPRODUCT 一样。

    【讨论】:

    • +1 这正是我所需要的。 N()T() 函数的“取消引用”功能让我感到惊讶。事实上,在公式 =SUMPRODUCT(N(INDIRECT("A"&ROW()))) 中,N() 函数实际上解决了 #VALUE 错误(如 Excel 2003 中的评估公式中所示)。这是非常好的知道。此外,关于 R/U 和 P/Q 类型参数的信息似乎确实是一个很好的解释。 P/Q 类型的xlTypeNil 元素的处理似乎与SUMPRODUCT() 的行为相匹配。感谢您的精彩回答。永远不会知道谷歌是为了什么。值得+10!!
    • 很高兴这有帮助 - Laurent Longre 最初发现了这种行为,并展示了如何参考 xlcall.h 使用 CALL 函数来处理工作表函数:cpearson.com/excel/Call.htm。在 VBA 中,仍然可以通过以下方式访问:ExecuteExcel4Macro
    【解决方案2】:

    ROW() 返回一个数组,使用INDEX 获取第一个元素。

    然后你的例子变成:=SUMPRODUCT(INDIRECT("A"&INDEX(ROW(),1)))

    【讨论】:

    • 感谢您的回答。我使用SUM() 函数而不是INDEX() 函数,并解决了这个问题。但是,我一直在寻找我为什么需要这样做的解释。
    • 这对我来说是最好的答案。在 SUMPRODUCT() 中使用的 ROW() 生成的数组上使用 INDEX() 是完美的!如果波动性完全与重新计算有关,那我就不会那么烦了,因为现在计算机速度要快得多。我的工作簿中使用了很多间接和偏移量,我可以接受长达 1 秒的重新计算延迟。因此,如果我需要在 SUMPRODUCT() 中使用 ROW(),那么 INDEX() 是必须的辅助函数!非常感谢 SeanC​​pan>
    • 哦,感谢 OP 自我回答的 SUM() 技巧。它缩短了公式,我更喜欢较短的公式。我想知道其中一个是否更快。也许 SUM() 更快,因为它是非易失性的?
    • sumproduct 不是易失性的。这些是 volatile 函数:msdn.microsoft.com/en-us/library/office/bb687891.aspx#Anchor_2
    【解决方案3】:

    我不认为 ROW() 在这里表现不同,它在两种情况下都返回一个数组。我假设 SUM 和 SUMPRODUCT 以不同的方式处理该数组 - 不知道为什么。

    许多函数或它们的组合返回数组 - 您不需要 CTRL+SHIFT+ENTER 来实现,在许多情况下您只需要 CSE 来处理创建的数组。

    我只会使用 INDEX 代替 INDIRECT(这也通过避免 volatile 函数使您受益),即

    =SUMPRODUCT(INDEX(A:A,ROW()))

    ....将其扩展到您的范围,此公式将计算 A 列范围内 > 1 的值的数量,其中 x 定义起始行,y 定义结束行

    =COUNTIF(INDEX(A:A,x):INDEX(A:A,y),">1")

    x和y可以通过公式计算

    如果要添加更多条件,您可以类似的方式使用 SUMPRODUCT 或 COUNTIFS

    【讨论】:

    • 感谢您的回答。我在ROW() 函数周围使用了SUM() 函数,并解决了这个问题。另外,对于我的特殊问题,我必须使用INDIRECT() 函数,因为单元格引用正在其他地方计算!当您说 CSE 只是更改数组的处理时,您似乎是对的。 @lori_m 对为什么 SUM()SUMPRODUCT() 以不同方式处理数组有一个很好的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多