用户定义函数计算混乱
User Defined Function calculation mess up
我有一个工作簿,其中有四个 sheets:
- 设置
- 产品 A
- 产品 B
- 概览
设置 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
我有一个工作簿,其中有四个 sheets:
- 设置
- 产品 A
- 产品 B
- 概览
设置 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