UDF 循环引用

UDF Circular reference

我有一个任务是创建几个 UDF,主要是为了将销售数据与基准进行比较,然后 return 一个基于相同值的整数,该值是 return 在前一个 [=21] 上编辑的=].我已经 运行 陷入臭名昭著的循环错误,这对我来说毫无意义,因为虽然我指的是 VBA 中禁止的单元格地址,但它仅在上下文中另一个 sheet。

如果我启用迭代计算,它会起作用,但有时它会继续迭代并只是抬高 return 值。这会影响整个工作簿。我觉得我在这里遗漏了一些简单的东西,但我缺乏 VBA 的经验来明确知道。如果有人有一个我可能会忽略的快速简单的修复方法,我将不胜感激。

我很聪明,打算在 Python 使用 xlwings 或 Java 使用 Apache POI 来做这件事。考虑一下我在 VBA 上放弃时的冰雹玛丽通行证。有什么想法吗?

Function tier1(Sales As Double) As Integer
    'Constant Declaration
    'Change these to alter benchmark values
    Const BENCH As Double = 133000#
    Const VARIANCE As Double = 0.9

    'Variable Declaration
    Dim callCell As String
    Dim sheet As Integer
    Dim oldValue As Integer
    Dim returnValue As Integer

    'Assigns Values to callCell & sheet
    sheet = ActiveSheet.Index
    callCell = Application.Caller.Address

    If sheet > 1 Then
        oldValue = Worksheets(sheet - 1).Range(callCell).Value
    Else
        oldValue = 0
    End If

    Select Case Sales
        Case Is >= BENCH
            Select Case oldValue
                Case Is > 0
                    returnValue = oldValue - 1
                Case Is > 2
                    returnValue = 2
                Case Else
                    returnValue = 0
            End Select
        Case Is < BENCH
            returnValue = oldValue + 1
            If Sales > (BENCH * VARIANCE) And returnValue > 2 Then
                returnValue = 2
            End If
        End Select

        tier1 = returnValue
End Function

在 UDF 中引用其他 sheet 时必须小心,您会得到您期望的 sheet。您的所有引用都应该是合格的,否则它们将默认为可能不是您所期望的内容。

例如:

oldValue = Worksheets(sheet - 1).Range(callCell).Value

等同于:

oldValue = ActiveWorkbook.Worksheets(sheet - 1).Range(callCell).Value

因此,如果包含您的公式的工作簿不是活动工作簿,您的结果可能与您预期的不同。

一些建议的修改:

Function tier1(Sales As Double) As Integer
    'Constant Declaration
    'Change these to alter benchmark values
    Const BENCH As Double = 133000#
    Const VARIANCE As Double = 0.9

    'Variable Declaration
    Dim callCell As Range
    Dim sheet As Integer
    Dim wb As Workbook
    Dim oldValue As Integer
    Dim returnValue As Integer

    Set callCell = Application.Caller
    Set wb = callCell.Worksheet.Parent
    sheet = callCell.Worksheet.Index

    If sheet > 1 Then
        oldValue = wb.Worksheets(sheet - 1).Range(callCell.Address).Value
    Else
        oldValue = 0
    End If

    Select Case Sales
        Case Is >= BENCH
            Select Case oldValue
                Case Is > 0
                    returnValue = oldValue - 1
                Case Is > 2
                    returnValue = 2
                Case Else
                    returnValue = 0
            End Select
        Case Is < BENCH
            returnValue = oldValue + 1
            If Sales > (BENCH * VARIANCE) And returnValue > 2 Then
                returnValue = 2
            End If
        End Select

        tier1 = returnValue
End Function