用户定义函数计算混乱

User Defined Function calculation mess up

我有一个工作簿,其中有四个 sheets:

设置 sheet 包含其他 sheet 用于计算的变量。

产品 A 和产品 B sheet 使用不同的 UDF 来计算增长收入和流失率。我们使用不同的 UDF,因为计算增长等的公式对于每个产品都是不同的。

概览显示产品 A 和产品 B 的总计。

现在问题如下。

当我计算 sheet 产品 A 时,它扰乱了产品 B 的值,反之亦然。

有什么想法吗?

已编辑:

UDF

Private Sub Workbook_SelectionChange(ByVal Target As Range)
    Calculate
End Sub
Public Function PSPGrowth(CurrentPos, DataColStart, CountryPSPNew, AvgDuration, Fee, Growth1, Growth2, Growth3, Growth4, Growth, CalcRange As Range)

  'recalculate on cell changes
Application.Volatile True
  'define variables
  Sum = 0
  PosCurrent = CurrentPos.Column()
  PSPNewRow = CountryPSPNew.Row()
  'calculate starting point
  PosStart = PosCurrent - AvgDuration

  If (PosStart <= DataColStart) Then
    PosStart = DataColStart
  End If

  'calculate duration
  Duration = 1 + PosCurrent - PosStart

  'loop new contracts
  For c = PosStart To PosCurrent
    'get new contracts
    NewContracts = Cells(PSPNewRow, c)
    If (NewContracts > 0) Then
        'get contract duration till current position
        ContractDuration = 1 + PosCurrent - c

        'calculate revenue growth according to contract duration
        If (ContractDuration < 13) Then
            'year 1
            cDuration = ContractDuration
            y1 = (1 + Growth1.Value / 12)

            Sum = Sum + (NewContracts * (1 + Growth1.Value / 12))

        ElseIf (ContractDuration > 12 And ContractDuration < 25) Then
            'year 2
            cDuration = ContractDuration - 12
            y1 = (1 + Growth1.Value)
            y2 = y1 * (1 + (cDuration * Growth2.Value / 12))

            Sum = Sum + (NewContracts * y2)

        ElseIf (ContractDuration > 24 And ContractDuration < 37) Then
            'year 3
            cDuration = ContractDuration - 24
            y1 = (1 + Growth1.Value)
            y2 = y1 * (1 + Growth2.Value)
            y3 = y2 * (1 + (cDuration * Growth3.Value / 12))

            Sum = Sum + (NewContracts * y3)

            'Sum = Sum + (NewContracts * (1 + Growth1.Value + Growth2.Value + Growth3.Value / 12))

        ElseIf (ContractDuration > 36 And ContractDuration < 49) Then
            'year 4
            cDuration = ContractDuration - 36
            y1 = (1 + Growth1.Value)
            y2 = y1 * (1 + Growth2.Value)
            y3 = y2 * (1 + Growth3.Value)
            y4 = y3 * (1 + (cDuration * Growth4.Value / 12))

            Sum = Sum + (NewContracts * y4)

    '        Sum = Sum + (NewContracts * (1 + Growth1.Value + Growth2.Value + Growth3.Value + Growth4.Value / 12))

        ElseIf (ContractDuration > 48) Then
            'year 5+
            cDuration = ContractDuration - 48
            y1 = (1 + Growth1.Value)
            y2 = y1 * (1 + Growth2.Value)
            y3 = y2 * (1 + Growth3.Value)
            y4 = y3 * (1 + Growth4.Value)
            y5 = y4 * (1 + (cDuration * Growth5.Value / 12))

            Sum = Sum + (NewContracts * y5)

            'Sum = Sum + (NewContracts * (1 + Growth1.Value + Growth2.Value + Growth3.Value + Growth4.Value + Growth5.Value / 12))
        Else
            Sum = Sum + 0
        End If
    End If
  Next

  'return result
  PSPGrowth = Sum * Fee.Value

End Function

Public Function PRODUCTAActive(CurrentPos, DataColStart, CountryBSNew, DropOutMonth, DropOutRate, CalcRange As Range)

  'recalculate on cell changes
  Application.Volatile True
  'define variables
  Sum = 0
  PosCurrent = CurrentPos.Column
  BSNewRow = CountryBSNew.Row()
  'calculate starting point
  PosStart = DataColStart
  If (PosStart <= DataColStart) Then
    PosStart = DataColStart
  End If
  'calculate duration
  Duration = 1 + PosCurrent - PosStart

  'loop new contracts
  For c = PosStart To PosCurrent
    'get new contracts
    NewContracts = Cells(BSNewRow, c)
    If (NewContracts > 0) Then
        'get contract duration till current position
        ContractDuration = 1 + PosCurrent - c

        'calculate revenue growth according to contract duration
        If (ContractDuration <= DropOutMonth) Then

            Sum = Sum + Round(NewContracts, 0)
        Else
            Sum = Sum + Round((NewContacts * (1 - DropOutRate)), 0)
        End If
    Else
        Sum = Sum + 0
    End If
  Next

  'return result
  PRODUCTAActive = Sum

End Function

Public Function PRODUCTAConvertionCalc(CurrentPos, DataColStart, CountryBSNew, ConvertionMonth, ConvertionRate, CalcRange As Range)

  'recalculate on cell changes
  Application.Volatile True
  'define variables
  Sum = 0
  PosCurrent = CurrentPos.Column
  BSNewRow = CountryBSNew.Row()
  'calculate starting point
  PosStart = DataColStart
  If (PosStart <= DataColStart) Then
    PosStart = DataColStart
  End If
  'calculate duration
  Duration = 1 + PosCurrent - PosStart

  'loop new contracts
  For c = PosStart To PosCurrent
    'get new contracts
    NewContracts = Cells(BSNewRow, c)
    If (NewContracts > 0) Then
        'get contract duration till current position
        ContractDuration = 1 + PosCurrent - c

        'calculate revenue growth according to contract duration
        If (ContractDuration = ConvertionMonth) Then

            Sum = Sum + Round(NewContracts * ConvertionRate, 0)
        Else
            Sum = Sum + 0
        End If
    Else
        Sum = Sum + 0
    End If
  Next

  'return result
  PRODUCTAConvertionCalc = Sum

End Function


Public Function PRODUCTACommissionCalc(CurrentPos, DataColStart, CountryBSNew, DropOutMonth, DropOutRate, ComY1, ComY2, PremiumPrice, CountryBSNewConv, ConvertionMonth, ConvertionRate, CalcRange1 As Range, CalcRange2 As Range)

  'recalculate on cell changes
  Application.Volatile True
  'define variables
  Sum = 0
  TotalCom = 0
  PosCurrent = CurrentPos.Column
  BSNewRow = CountryBSNew.Row()
  'calculate starting point
  PosStart = DataColStart
  If (PosStart <= DataColStart) Then
    PosStart = DataColStart
  End If
  'calculate duration
  Duration = 1 + PosCurrent - PosStart

  'loop new contracts
  For c = PosStart To PosCurrent
    'get new contracts
    NewContracts = Cells(BSNewRow, c)
    If (NewContracts > 0) Then
        'get contract duration till current position
        ContractDuration = 1 + PosCurrent - c

        'calculate revenue from new contracts
        If (ContractDuration <= DropOutMonth) Then
            If (ContractDuration <= 12) Then
               TotalCom = TotalCom + Round(NewContracts, 0) * ComY1 * PremiumPrice
            Else
               TotalCom = TotalCom + Round(NewContracts, 0) * ComY2 * PremiumPrice
            End If
        Else
            If (ContractDuration <= 12) Then
               TotalCom = TotalCom + Round((NewContacts * (1 - DropOutRate)), 0) * ComY1 * PremiumPrice
            Else
               TotalCom = TotalCom + Round((NewContacts * (1 - DropOutRate)), 0) * ComY2 * PremiumPrice
            End If
        End If

    Else
        TotalCom = TotalCom + 0
    End If
  Next

  ' converted contracts
  BSNewRow = CountryBSNewConv.Row()
   'loop new contracts
  For c = PosStart To PosCurrent
    'get new contracts
    NewContracts = Cells(BSNewRow, c)
    If (NewContracts > 0) Then
        'get contract duration till current position
        ContractDuration = 1 + PosCurrent - c

        'calculate revenue growth according to contract duration
        If (ContractDuration >= ConvertionMonth) Then
            If (ContractDuration <= 12) Then
               TotalCom = TotalCom + Round(NewContracts * ConvertionRate, 0) * ComY1 * PremiumPrice
            Else
               TotalCom = TotalCom + Round(NewContracts * ConvertionRate, 0) * ComY2 * PremiumPrice
            End If
        Else
           TotalCom = TotalCom + 0
        End If
    Else
        TotalCom = TotalCom + 0
    End If
  Next

  'return result
  PRODUCTACommissionCalc = TotalCom

End Function

您的问题出在这一行:

NewContracts = Cells(PSPNewRow, c)

这里的Cells调用总是指activesheet。我怀疑你想要这个:

NewContracts = CountryBSNew.Worksheet.Cells(PSPNewRow, c).Value