简体   繁体   中英

UDF Circular reference

I have a task with creating a couple UDF's mainly to compare sales figures against a benchmark and then return an integer based on the same value which was returned on a previous sheet. I've run into a the infamous circular error which makes no sense to me because while I am referring to the address of the cell which is a no-no in VBA, it's only in the context of another sheet.

If I enable iterative calculations, it works but then on occasion the it continues to iterate and just jacks the return value up. Which affects the entire workbook. I feel like I'm missing something simple here but I lack the experience with VBA to know explicitly. If someone has a quick easy fix that I might be overlooking I'd much appreciate it.

I'm about at wits and and going to just do this in Python using xlwings or Java using Apache POI. Consider this my hail mary pass at giving up on VBA. Any ideas?

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

Have to be careful when referring to other sheets within a UDF that you get the sheet you expect. All your references should be qualified, otherwise they will default to something which might not be what you expect.

For example:

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

is the same as:

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

so if the workbook containing your formula isn't the active workbook, your results are likely to not be what you expect.

A few suggested edits:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM