如果我编辑另一个工作表并切换回来,则不显示易失性 UDF 的结果

Posted

技术标签:

【中文标题】如果我编辑另一个工作表并切换回来,则不显示易失性 UDF 的结果【英文标题】:Result of volatile UDF isn't shown if I edit another Sheet and switch back 【发布时间】:2019-04-08 21:32:53 【问题描述】:

我正在使用一个 volatile UDF,它基本上可以正常工作。我将一个范围传递给它,如果这个范围内的值发生变化,它会重新计算它应该。但是当我切换到另一个工作表并编辑例如一个单元格然后切换回来时,我看不到这个 UDF 的输出。

我已经更改了包含 UDF 的工作表上的单元格值或保存文件,它再次显示 UDF 的输出。我也可以做一个

' Refresh all Calculations if Sheet is activated
Private Sub Worksheet_Activate()
    Application.CalculateFull
End Sub

但如果不是非常需要,我认为这不是一个很好的解决方案,因为工作表包含数百个公式。

我还检查了UDF #Value! when switching sheets,这似乎是类似的问题(没有真正的答案)。

' Returns Tags-String based on Range/Threshold
Public Function GetTagsString(rngRange As Range) As String
    ' Define Variables
    Dim strTags As String
    Dim strTagSeparator As String
    Dim strTag As String
    Dim intTagRow As Integer
    Dim intTagValue As Integer
    Dim dblTagMinScore As Double
    Dim rngCell As Range

    ' Initialize Values
    intTagRow = Sheets("Locations").Range("TagsRow").Value
    dblTagMinScore = Sheets("Settings").Range("TagMinScore").Value
    strTagSeparator = Sheets("Settings").Range("TagSeparator").Value
    strTags = ""

    ' Loop through all Cells in Range
    For Each rngCell In rngRange
        intTagValue = rngCell.Value
        strTag = Cells(intTagRow, rngCell.Column).Value

        ' Include Tag if equal/greater than Tag-Threshold
        If (intTagValue >= dblTagMinScore) Then
            If (Not strTags = "") Then
                ' String contains already Tags => append Tag-Separator
                strTags = strTags & strTagSeparator & strTag
            Else
                strTags = strTag
            End If
        End If
    Next rngCell

    ' Return Tags-String
    GetTagsString = strTags
End Function

我通过以下方式调用此 UDF:

=GetTagsString(INDIRECT(ADDRESS(ROW();COLUMN(TagAmusement);4)):INDIRECT(ADDRESS(ROW();COLUMN(TagFun);4)))

TagAmusement 和 TagFun 是命名单元。我知道使用 INDIRECT 可能不是最好的解决方案,但由于几个原因,我需要保持这种活力。我在很多公式中都这样做,但没有使用 UDF,也没有同样的问题。问题一定是和UDF有关,但我不认为是因为这个函数参数。它一定与更改另一张表并切换回原始表有关。

是的,我从工作表中读取了一些值,但我也尝试过传递它们,但没有任何区别(我也没有更改(d)它们)。

唯一有效的(在自动化基础上)是:

' Refresh all Calculations if Sheet is activated
Private Sub Worksheet_Activate()
    Application.CalculateFull
End Sub

仅当我更改工作表并在那里执行“某些操作”(例如编辑单元格)时才会出现问题。

这是 Excel 的错误还是我忽略了什么?

【问题讨论】:

【参考方案1】:

strTag = Cells(intTagRow, rngCell.Column).ValuestrTag = ActiveSheet.Cells(intTagRow, rngCell.Column).Value 相同

因此,如果rngRange 在“Sheet1”上,但您随后切换到“Sheet2”并编辑单元格(这会触发重新计算),则读入strTag 的值将来自 Sheet2 而不是来自 Sheet1。如果 Sheet2 上的相应单元格恰好是空的,那么它看起来好像 UDF 没有返回任何内容。

为防止出现这种情况,请指定对 Cells 的调用适用于的工作表:

strTag = rngRange.Worksheet.Cells(intTagRow, rngCell.Column).Value

或将整个 For Each 循环包装在 With...End With 块中,并使用该对象调用 Cells:

With rngRange.Worksheet
    For Each rngCell In rngRange
    '...
        strTag = .Cells(intTagRow, rngCell.Column).Value
    '...
    Next rngCell
End With

【讨论】:

非常感谢!它完美地工作:)也感谢您的解释-现在完全有道理,我在旁边寻找“一切”。

以上是关于如果我编辑另一个工作表并切换回来,则不显示易失性 UDF 的结果的主要内容,如果未能解决你的问题,请参考以下文章

C++ 易失性成员函数

函数没有易失性。怎么修?

在这个多线程 C++ 代码中是不是需要“易失性”?

易失性变量和非易失性重新排序/可见性

将易失性数组转换为非易失性数组

Java 内存模型:易失性变量和发生前