簡體   English   中英

EXCEL解算器,VBA在啟動解算器之前會調用不需要的函數

[英]EXCEL solver, VBA calls unwanted function before launching the solver

我正在編寫一個代碼,該代碼應計算各種不同金融證券的公允價值。 這些證券來自不同的發行人,因此將它們按國家分組,然后進行評估。

為此,我需要為每個組/國家/地區設置6個參數,不幸的是這些參數不是固定的,但每天都會更改。 每次運行模型時,我都需要重新計算它們,因此我編寫了一個子例程來優化求解器的此問題。

到目前為止,它在大多數時間都有效,但是有時在午餐前,vba代碼進入了同一電子表格的其他功能,並更改了問題的起始值(作為前一天的參數讀取)。 Solver子例程中未提及這些功能,甚至在同一模塊或工作表中也未提及。

知道為什么會這樣嗎? 關於如何防止VBA跨入有害功能的任何想法?

這是我的求解器代碼

Sub NSCoeff()
Dim current_wb As String
current_wb = ThisWorkbook.Name


Workbooks(current_wb).Sheets("Nelson_Siegel").Calculate
Workbooks(current_wb).Sheets("Nelson_Siegel").Activate
SolverReset
SolverOptions Precision:=0.01, Convergence:=0.1, AssumeNonNeg:=False
SolverOk SetCell:="$N$9", MaxMinVal:=2, ValueOf:=0, ByChange:="$N$4:$S$4", _
    Engine:=1, EngineDesc:="GRG Nonlinear"
SolverAdd CellRef:="$N$4", Relation:=3, FormulaText:="0.001"
SolverAdd CellRef:="$S$4", Relation:=3, FormulaText:="0.001"
SolverOk SetCell:="$N$9", MaxMinVal:=2, ValueOf:=0, ByChange:="$N$4:$S$4", _
    Engine:=1, EngineDesc:="GRG Nonlinear"
SolverOk SetCell:="$N$9", MaxMinVal:=2, ValueOf:=0, ByChange:="$N$4:$S$4", _
    Engine:=1, EngineDesc:="GRG Nonlinear"
SolverSolve userFinish:=True

End Sub

最后一行之后,代碼立即進入此函數

Function Discount_Quartic(a As Double, b As Double, c As Double, d As Double, t As Double) As Double
Dim dr, r As Double
Application.Volatile

r = Worksheets("ImpBond").Cells(4, 26).Value
dr = Worksheets("ImpBond").Cells(4, 27).Value
Discount_Quartic = a * Exp(-r * t) + b * Exp(-r * t * dr) + c * Exp(-r * t * dr ^ 2) + d * Exp(-r * t * dr ^ 3) + (1 - a - b - c - d) * Exp(-r * dr ^ 4 * t)
End Function

謝謝您的幫助!

這取決於:

Application.Volatile

該方法告訴應用程序該函數是Volatile 換句話說, 每次對電子表格進行更改時都必須重新計算該函數。

因此:

  • 您可以通過子NSCoeff修改電子表格;
  • Application看到什么是Volatile然后重新計算所有內容。 您的情況是Discount_Quartic Voilàvoilà

在此處找到有關Application.Volatile方法的更多信息。

至於關於如何防止VBA跨入有害功能的任何想法? ,您有兩種解決方案(可能更多,但是現在我想到了這些):

  • 從功能中刪除Application.Volatile 但是,這將不再提示重新計算該函數(除非您沒有明確地重新計算它)。
  • 做一個小技巧,我將通過一個簡單的示例向您展示:

     Dim dontCall As Boolean '<-- default: False Sub dontCallTheFunction() Range("A1") = 1 '<-- recalculation prompted, we will get into the function dontCall= True'<-- we don't want the function to be recalculated End Sub Function myFunction() Application.Volatile If dontCall= False Then myFunction = 3 Else dontCall = False '<-- reset the value to False, so next time we'll calculate it normally End If End Function 

如果根據昨天的數據來確定Solver的參數為靜態值,則應為這些值制作一個靜態副本以用於Solver。 我懷疑您的參數是計算的結果,其中包括折扣的日期等(以及費率,優惠券)。 因此,當您打開工作簿時,這些計算將得到更新(如@ Matteo NNZ所述,上面的函數被標記為volatile),因此Solver開始使用新值。

根據您的代碼,Solver嘗試通過更改單元格N4:S4來使單元格N9最小化,但同時使N4和S4均≥0.001。

我遇到了與您完全相同的問題,發現您想回答我的問題。 我同意ChipsLetten的意見,然后看了一下電子表格,發現我具有該功能的單元格。 因此,請檢查您的電子表格是否在某些單元格中未使用Discount_Quadratic

(如具有公式“ = Discount_Quadratic(a,b,c,d,t)”的單元格A1)

如果您在電子表格的單元格中具有此功能,則Excel將運行此功能,等於沒有此功能的任何單元格。 因此,當Excel更新所有電子表格的公式時,即使您沒有真正調用它,在任何時候您的代碼都會被此更新中斷並在此函數內運行代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM