UDF - 自动运行时的结果与遍历时的结果不同

Posted

技术标签:

【中文标题】UDF - 自动运行时的结果与遍历时的结果不同【英文标题】:UDF - different results when auto-ran than when walked through 【发布时间】:2016-10-04 14:50:52 【问题描述】:

我有以下 UDF,保存在我的工作簿的一个模块中:

Function sumAbove2(myCell As Range)

Dim rng As Range, cel As Range
Dim topRow As Long
topRow = myCell.Offset(0, -2).End(xlUp).Row
Dim sRng As Range, eRng As Range
Set sRng = Cells(myCell.Row, myCell.Column)
Set eRng = Cells(topRow, myCell.Column)

For Each cel In Range(sRng, eRng)
    Debug.Print cel.Address
    sumAbove2 = cel.Value + sumAbove2
Next cel

End Function

这个想法是自动总结信息的“块”。

当我使用 F8 遍历 UDF 时,它工作得很好。但是,当自动运行时,它会产生意想不到的结果。令人讨厌的是,我已将此代码放在一个全新的工作簿中,放入示例数据,并且它从未产生不正确的结果……因此,我向我的 SO 朋友道歉,我无法让它重现。我对 UDF 比较陌生,所以可能会遗漏一些关于运行它们的关键点(波动性有帮助/伤害吗?)

当我这样做时,两秒钟后,在宏中使用 Break,我可以按 F8 单步执行,它正确地不添加任何内容,并返回 0

会发生什么?我没有在代码中指定工作表,但我不明白为什么会修复它。它可能与页面上的其他一些公式有关吗?没有 worksheet_change 等事件。

编辑:工作簿有几张表,这些表中有公式。但是我正在运行的工作表都是文本,保存我试图输入的公式。只是想提一下,以防格式化中的某些东西可能会产生奇怪的行为。

【问题讨论】:

第 2 列的值是否被公式填满了? @ScottCraner - 不,所有信息。是文本(格式为“常规”)。唯一的公式是我正在尝试使用的“总和”公式。 您的函数需要是 volatile 的,并且在计算时会根据当时的活动工作表进行计算。 UDF 确实应该接受它所需的所有范围作为 直接 参数。 如果您选择两列中的单元格并按 Ctrl-Up,它是否会超出您的预期? 想一想:试一试,用myCell.Parent.Cells(... 完全限定您的代码。关于Application.Volatile,我想指出,这只是确保每次在工作表上更改值时都会重新计算公式。否则,如果值(应该总结)正在变化,则该公式似乎提供了不正确的结果。当然,要使其正常工作,您还需要将文件设置为 Application.Calculation = xlCalculationAutomatic 【参考方案1】:

我会 1) 稍微简化一下代码(您没有将 rng 变量用于任何事情,并且您实际上并不需要单独变量中的开始和结束行范围),2) 将数据类型定义为被返回,3) 使用完全限定的引用和 4) 通过以下方式添加数字检查:

Function sumAbove2(myCell As Range) As Double

    Dim actSht As Excel.Worksheet
    Dim topRow As Long
    Dim cel As Range, searchRng As Range

    topRow = myCell.Offset(0, -2).End(xlUp).Row

    Set actSht = ActiveSheet
    With actSht
        Set searchRng = .Range(.Cells(myCell.Row, myCell.Column), .Cells(topRow, myCell.Column))
    End With

    For Each cel In searchRng
        If IsNumeric(cel.Value) Then sumAbove2 = cel.Value + sumAbove2
    Next cel

End Function

我似乎可以完美地工作。

【讨论】:

谢谢你 - 我试过了,它对我也有同样的效果!我自动运行它,并得到不正确的结果。当我逐步完成时,我得到了正确的结果......嗯。 这似乎有些牵强,但您尝试过重启吗?在极少数情况下,我会遇到 Excel 应用程序出现故障的情况,因为 Windows 中暂时出现了问题。 没有什么是牵强附会了!我尝试重新启动,出现同样的问题:/ 当包含公式的工作表不是活动工作表时,这将给出不正确的结果。 @BruceWayne 由于有问题的工作簿的行为不稳定,我最好的猜测是您的工作簿或 Excel 应用程序以某种方式损坏。 1) 在另一台计算机上测试您的工作簿。如果问题仍然存在: 2) 作为最后的手段,我会尝试在新工作簿中运行代码,然后我会逐步重新创建旧工作簿,直到可以查明问题。 (如果问题消失,那么工作簿就坏了),如果旧工作簿很大,这显然是一项艰巨的任务,但如果其他一切都失败了,这可能是您的最佳选择。【参考方案2】:

您需要使用正确的工作表完全限定您的所有范围...

Function sumAbove2(myCell As Range)

    Dim sht As Worksheet '<<<
    Dim rng As Range, cel As Range
    Dim topRow As Long
    Dim sRng As Range, eRng As Range

    Set sht = myCell.Worksheet '<<<

    topRow = myCell.Offset(0, -2).End(xlUp).Row

    Set sRng = sht.Cells(myCell.Row, myCell.Column) '<<<
    Set eRng = sht.Cells(topRow, myCell.Column)     '<<<

    For Each cel In sht.Range(sRng, eRng) '<<<
        Debug.Print cel.Address
        sumAbove2 = cel.Value + sumAbove2
    Next cel

End Function

编辑:从工作表调试 UDF #VALUE 错误很棘手 - 如果您通过从测试子调用函数进行调试,您将获得更多信息:

Sub Tester()
    Debug.Print sumAbove2(Activesheet.Range("C44"))
End sub

【讨论】:

嘿蒂姆-谢谢你。我完全限定了它们,但仍然得到了意想不到的结果。我现在将专注于查看工作表/工作簿,了解导致此问题的一些时髦代码/格式。非常感谢,它恢复了排位赛范围的重要性(我通常非常热衷于这样做,我只是在这里忘记了)。当我运行它时,作为 only 宏,它返回 #VALUE 错误。当我逐步完成它时,它正确地给出了准确的总和。所以,something 在书中很时髦。

以上是关于UDF - 自动运行时的结果与遍历时的结果不同的主要内容,如果未能解决你的问题,请参考以下文章

使用 EXECUTE 从 SQL Server 调用用户定义函数时的标量结果不同

多次运行该函数时的结果不同 - C.

前端客户端自动构建

python自动运行.exe文件并保存结果

jQuery自动完成:以不同方式显示某些对象?

打开自动布局时的 UIScrollView(故事板)