vba操作规划求解
vba操作規(guī)劃求解
- 要前期引用
- 用到的函數(shù)
- 1,SolverReset
- 2,SolverOk 函數(shù)
- 3,SolverAdd 函數(shù)
- 4,SolverFinish 函數(shù)
- 5,SolverSolve 函數(shù)
- 一個(gè)簡單案例
要前期引用
要使用vba操作規(guī)劃求解,需要添加引用Solver
Program Files\Microsoft Office\Office14\Library\SOLVER 子文件夾中的 Solver.xlam
可以用代碼直接操作,需彈窗后點(diǎn)擊信任對VBA工程對象模型的訪問
Sub 用vba代碼添加模型信任和前期引用規(guī)劃求解()Dim oWshell, iSet oWshell = CreateObject("WScript.Shell")Application.ScreenUpdating = False'信任對VBA工程對象模型的訪問oWshell.RegWrite "HKEY_CURRENT_USER\Software\Microsoft\Office" & Application.Version & "\Excel\Security\AccessVBOM", 1, "REG_DWORD" '信任對 VBA 項(xiàng)目的訪問With Application.SendKeys "~".CommandBars.FindControl(ID:=3627).ExecuteEnd WithAddIns("規(guī)劃求解加載項(xiàng)").Installed = TrueWith ThisWorkbook.VBProjectFor i = 1 To .References.CountIf .References(i).Name = "Solver" ThenExit SubElseIf i = .References.Count ThenThisWorkbook.VBProject.References.AddFromFile "SOLVER.XLAM"End IfEnd IfNext iEnd WithApplication.ScreenUpdating = True End Sub用到的函數(shù)
1,SolverReset
重置 “規(guī)劃求解參數(shù)” 對話框中的所有單元格選定區(qū)域和約束
2,SolverOk 函數(shù)
定義基本求解器模型。 相當(dāng)于在"數(shù)據(jù)分析**“組中單擊**“規(guī)劃求解”,然后在"規(guī)劃求解參數(shù)” | 對話框中指定 選項(xiàng)。
SolverOk ( SetCell、MaxMinVal、ValueOf、ByChange、Engine、EngineDesc )
- SetCell 是 Variant 類型的可選參數(shù)(不要給單元格,給單元格地址)。 引用活動(dòng)工作表中的一個(gè)單元格。 對應(yīng)于" 規(guī)劃求解參數(shù) "對話框中的"設(shè)置 目標(biāo)單元格 "框。
- MaxMinVal 是 Variant 類型的可選參數(shù)。 對應(yīng)于"規(guī)劃求解參數(shù)"對話框中 的"最大值"、最小值 和"值" 選項(xiàng)。
| 1 | 最大 |
| 2 | 最小化 |
| 3 | 匹配特定值 |
- ValueOf 是 Variant 類型的可選參數(shù)。 如果 MaxMinVal 為 3,則必須指定目標(biāo)單元格匹配到的值。
- ByChange 是 Variant 類型的可選參數(shù)(不要給單元格,給單元格地址)。 將更改的單元格或單元格范圍,以便在目標(biāo)單元格中獲得所需的結(jié)果。 對應(yīng)于"規(guī)劃 求解參數(shù)" 對話框中的"通過 更改單元格" 框。
- Engine 是 Variant 類型的可選參數(shù)。 應(yīng)用來求解問題的求解方法:2 表示單純形 LP 方法,1 表示 GRG 非線性方法,或 3 表示演進(jìn)式方法。 對應(yīng)于" 規(guī)劃求解參數(shù) “對話框中的"選擇求解 方法” 下拉列表。
- EngineDesc 是 Variant 類型的可選參數(shù)。 另一種以字符串形式指定應(yīng)用來求解問題的求解方法的方式:“單純形 LP”、“GRG 非線性”或“演進(jìn)式”。 對應(yīng)于" 規(guī)劃求解參數(shù) “對話框中的"選擇求解 方法” 下拉列表。
3,SolverAdd 函數(shù)
向當(dāng)前問題添加一個(gè)約束。 相當(dāng)于在"數(shù)據(jù)分析" 組中 單擊"規(guī)劃求解",然后單擊"規(guī)劃求解參數(shù)"對話框中 | 的"添加"。
SolverAdd ( CellRef 、Relation、FormulaText )
- CellRef 必需 Variant。 對單元格或單元格區(qū)域的引用(給地址,別直接給單元格),該引用構(gòu)成約束條件的左邊部分。
- Relation 必需 Integer。 約束左側(cè)和右側(cè)的算術(shù)關(guān)系。 如果選擇 4、5 或 6,則 CellRef 必須引用決策變量單元格,并且不應(yīng)指定 FormulaText。
| 1 | <= |
| 2 | = |
| 3 | >= |
| 4 | CellRef 引用的單元格必須具有整數(shù)的最終值。 |
| 5 | CellRef 引用的單元格的最終值必須為 0 (0) 1。 |
| 6 | CellRef 引用的單元格必須具有所有不同和整數(shù)的最終值。 |
- FormulaText 可選 Variant。 約束的右側(cè)。
4,SolverFinish 函數(shù)
指示 Microsoft Office Excel 如何處理結(jié)果,以及要在解決方案過程完成時(shí)生成哪種報(bào)表。
SolverFinish (KeepFinal、ReportArray、OutlineReports **** **** )
- KeepFinal 是 Variant 類型的可選參數(shù)。 可取值為 1 或 2。 如果 KeepFinal 為 1 或省略,則最終的解決方案值將保留在更改的單元格中,以替換任何以前的值。 如果 KeepFinal 值為 2,最終解決方案值遭放棄,并還原原有值。
- ReportArray 是 Variant 類型的可選參數(shù)。 Excel 在求解器完成時(shí)生成的報(bào)表種類:
- 當(dāng)使用“單工 LP”或“GRG 非線性求解”方法時(shí),1 會(huì)創(chuàng)建一個(gè)“解答”報(bào)告,2 會(huì)創(chuàng)建一個(gè)“敏感度”報(bào)告,3 會(huì)創(chuàng)建一個(gè)“限制”報(bào)告。
- 如果使用的是演進(jìn)式求解方法,1 表示生成“答案”報(bào)表,2 表示生成“總體”報(bào)表。
- 當(dāng) SolverSolve 返回 5 (規(guī)劃求解找不到可行解) ,1 創(chuàng)建一個(gè)"可行報(bào)告",2 創(chuàng)建一個(gè)Feasibility-Bounds報(bào)告。
- 當(dāng) SolverSolve 返回 7 時(shí)(不滿足線性條件),1 會(huì)創(chuàng)建“線性”報(bào)告。
- 使用 Array 函數(shù)可指定要顯示的報(bào)告,例如,ReportArray:= Array(1,3)。 OutlineReports 是 Variant 類型的可選參數(shù)。 可以是 True 或 False。 如果 OutlineReports 為 False 或省略,則報(bào)告以"常規(guī)"格式生成,而不進(jìn)行分級(jí)顯示。 如果 OutlineReports 值為 True,生成的報(bào)表包含對應(yīng)于你為決策變量和限制輸入的單元格范圍的大綱顯示組。
5,SolverSolve 函數(shù)
開始執(zhí)行規(guī)劃求解的求解過程。 相當(dāng)于單擊 “規(guī)劃求解參數(shù)” 對話框中的 “求解”。
SolverSolve ( UserFinish 、ShowRef)
- UserFinish 可選 Variant。 如果為 True,則返回結(jié)果,而不顯示“規(guī)劃求解結(jié)果”對話框。 如果為 False 或忽略,則返回結(jié)果,并顯示“規(guī)劃求解結(jié)果”對話框。 ShowRef 可選 Variant。 可以將宏的名稱作為字符串 (作為 ShowRef) 傳遞。 之后,只要規(guī)劃求解由于下列某個(gè)原因而暫停,便會(huì)調(diào)用此宏,而不是顯示“顯示試解”對話框。
- ShowRef 宏必須具有簽名 函數(shù) 名稱 (Reason As Integer)。 參數(shù) Reason 是 從 1 到 5 的整數(shù)值:
- 由于選中 “規(guī)劃求解選項(xiàng)” 對話框中的 “顯示迭代結(jié)果” 框而在每次迭代時(shí)調(diào)用的函數(shù),或者由于用戶按 Esc 來中斷規(guī)劃求解而調(diào)用的函數(shù)。
- 由于超過 “規(guī)劃求解選項(xiàng)” 對話框中的 “最長運(yùn)算時(shí)間” 限制而調(diào)用的函數(shù)。
- 由于超過 “規(guī)劃求解選項(xiàng)” 對話框中的 “迭代次數(shù)” 限制而調(diào)用的函數(shù)。
- 由于超過 “規(guī)劃求解選項(xiàng)” 對話框中的 “最大子問題數(shù)” 限制而調(diào)用的函數(shù)。
- 由于超過 “規(guī)劃求解選項(xiàng)” 對話框中的 “最大可行解數(shù)” 限制而調(diào)用的函數(shù)。
SolverSolve 返回值
如果尚未完整定義規(guī)劃求解問題,則 SolverSolve 會(huì)返回 #N/A 錯(cuò)誤值。 否則,規(guī)劃求解將會(huì)運(yùn)行,并且 SolverSolve 返回與“規(guī)劃求解結(jié)果”對話框中顯示的消息相對應(yīng)的整數(shù)值:
| 0 | 規(guī)劃求解找到解。 滿足所有約束和最優(yōu)條件。 |
| 1 | 規(guī)劃求解已收斂到當(dāng)前解。 滿足所有約束。 |
| 2 | 規(guī)劃求解無法改進(jìn)當(dāng)前解。 滿足所有約束。 |
| 3 | 當(dāng)超過最大迭代次數(shù)限制時(shí)選擇“停止”。 |
| 4 | “目標(biāo)單元格”值不收斂。 |
| 5 | 規(guī)劃求解找不到可行解。 |
| 6 | 規(guī)劃求解已根據(jù)用戶的請求而停止。 |
| 7 | 不滿足此 LP 規(guī)劃求解需要的線性條件。 |
| 8 | 問題太大,規(guī)劃求解無法處理。 |
| 9 | 規(guī)劃求解在目標(biāo)或約束單元格中遇到錯(cuò)誤值。 |
| 10 | 當(dāng)超過最長運(yùn)算時(shí)間限制時(shí)選擇“停止”。 |
| 11 | 內(nèi)存不足,無法解決問題。 |
| 13 | 模型出錯(cuò)。 請驗(yàn)證所有單元格和約束是否有效。 |
| 14 | 規(guī)劃求解在允許誤差范圍內(nèi)找到整數(shù)解。 滿足所有約束。 |
| 15 | 達(dá)到最大可行 [整數(shù)] 解數(shù)時(shí)選擇“停止”。 |
| 16 | 達(dá)到最大可行 [整數(shù)] 子問題數(shù)時(shí)選擇“停止”。 |
| 17 | 規(guī)劃求解在概率上收斂于一個(gè)全局解。 |
| 18 | 所有變量都必須擁有上限和下限。 |
| 19 | 二進(jìn)制或所有不同約束中的變量界限沖突。 |
| 20 | 變量上下限禁止全部可行解。 |
示例代碼
Worksheets("Sheet1").Activate SolverReset SolverOptions Precision:=0.001 SolverOK SetCell:=Range("TotalProfit"), _MaxMinVal:=1, _ByChange:=Range("C4:E6") SolverAdd CellRef:=Range("F4:F6"), _Relation:=1, _FormulaText:=100 SolverAdd CellRef:=Range("C4:E6"), _Relation:=3, _FormulaText:=0 SolverAdd CellRef:=Range("C4:E6"), _Relation:=4 SolverSolve UserFinish:=False, ShowRef:= "ShowTrial" SolverSave SaveArea:=Range("A33")Function ShowTrial(Reason As Integer)Msgbox ReasonShowTrial = 0 End Function一個(gè)簡單案例
已知A-C列,根據(jù)F-G列客戶和金額,找到票號(hào)組合
先定義一個(gè)函數(shù),操作規(guī)劃求解
設(shè)置主函數(shù)
Sub result()Dim r, dic, rng As Range, i, arData, ssKey$Set dic = CreateObject("Scripting.Dictionary")Application.ScreenUpdating = Falser = Range("a65536").End(xlUp).RowarData = Range("a1").Resize(r, 3).ValueFor i = 2 To r '用二級(jí)字典記錄每個(gè)客戶的單元格范圍ssKey = arData(i, 1)If dic.Exists(ssKey) = False ThenSet dic(ssKey) = CreateObject("Scripting.Dictionary")Set dic(ssKey) = Range("d" & i)ElseSet dic(ssKey) = Union(dic(ssKey), Range("d" & i))End IfNextr = Range("f65536").End(xlUp).RowFor i = 2 To rssKey = Range("f" & i).ValueIf dic.Exists(ssKey) ThenSet rng = dic(ssKey)Range("d1:d19").ClearContentsRange("h" & i).Value = MySolver([d1], Range("g" & i).Value, rng)End IfNextApplication.ScreenUpdating = True End Sub其他規(guī)劃求解vba函數(shù)幫助可以看官方文檔
https://docs.microsoft.com/zh-cn/office/vba/excel/concepts/functions/using-the-solver-vba-functions
總結(jié)
- 上一篇: python向数据库中添加参数_第四篇:
- 下一篇: softmax ce loss_手写so