用户定义函数计算陷入困境

时间:2015-11-23 10:22:25

标签: excel vba excel-vba user-defined-functions

我有一张有四张纸的工作簿:

  • 设置
  • 产品A
  • 产品B
  • 概述

设置表包含其他工作表用于计算的变量。

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

概述介绍产品A和产品B的总计。

现在问题如下。

当我计算产品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

1 个答案:

答案 0 :(得分:0)

你的问题在这一行:

NewContracts = Cells(PSPNewRow, c)

此处Cells来电将始终引用有效表。我怀疑你想要这个:

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