当我通过VBA使用Solver时,我遇到了这个非常奇怪的错误。我的目标和更改单元格在第1页上,每当我得到一个优化的解决方案时,我都希望将优化的更改单元格复制到表格2(我这样做几次,因为每次我的优化功能都会改变)。如果我在我的Solver程序中添加了Worksheets(1).Select
,那么Solver工作正常并将值粘贴到第2页。但是,如果我删除了这个语句并运行了Solver并选择了第2张而不是第1张,那么我首先会看到类似"设置问题..."在状态栏然后我得到了错误的结果,也是一个奇怪的" 0"在我的工作表2.我使用VBA调试器,发现这" 0"在Call SolverSolve(True)
语句之后出现了值,所以我怀疑这个bug只是在Solver中。仅当活动工作表位于更改单元格和目标单元格时,才能运行求解器吗?或者我在哪里做错了?
Option Explicit
Function SAMPLEONCE()
'Create one sample from 2500 MI data in worksheets("P2 MI Data"), the sample is
'stored in worksheets("P2 Sample")
Const n As Long = 2500
Dim temp As Long
Randomize
temp = Int(Rnd * 2500) + 1
SAMPLEONCE = Worksheets("P2 MI Data").Cells(temp + 1, 1).Resize(1, 6)
End Function
Sub SolveItOnce()
Call solverreset
Call solverok(Worksheets("P2 Sample").Range("Output"), 2, 0, Worksheets("P2 Sample").Range("Input"))
Call solversolve(True)
End Sub
Sub SolveIt()
Dim i As Long, j As Long, k As Long
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Worksheets("P2 Sample").Activate
For i = 1 To 100
'Sampling
For j = 1 To 1000
Worksheets("P2 Sample").Range("Sample").Rows(j).FormulaArray = "=SAMPLEONCE()"
Next j
Worksheets("P2 Sample").Range("Sample").Copy
Worksheets("P2 Sample").Range("Sample").PasteSpecial Paste:=xlPasteValues
'Call Solver
For k = 1 To 3
Call SolveItOnce
Next k
'Output result
Worksheets("P2 Sample").Range("A2:G2").Copy
Worksheets("P2 Result").Range("A1:G1").Offset(i, 0).PasteSpecial Paste:=xlPasteValues
Next i
Application.Calculation = xlCalculationAutomatic
End Sub
答案 0 :(得分:0)
我没有查看完整的代码,而是处理例程SolveItOnce
...
Sub SolveItOnce()
Call solverreset
Call solverok(Worksheets("P2 Sample").Range("Output"), 2, 0, Worksheets("P2 Sample").Range("Input"))
Call solversolve(True)
End Sub
有一个(因为没有更好的词)bug associated with the use SolverReset。我建议你省略它。您对SolverOK的调用将解决您的问题。
调用SolverOK时,SetCell
和ByChange
的输入需要是字符串,而不是范围。此外,为了确保解算器引用正确的工作表,最好使用工作表名称“完全限定”字符串中的范围。我建议您的代码看起来像这样(已编译但未经过测试)......
Sub SolveItOnce()
Dim myRng As Range, SetAddress As String, ChngAddress As String
Set myRng = Worksheets("P2 Sample").Range("Output")
SetAddress = Split(myRng.Address(external:=True), "[")(0) & Split(myRng.Address(external:=True), "]")(1)
Set myRng = Worksheets("P2 Sample").Range("Input")
ChngAddress = Split(myRng.Address(external:=True), "[")(0) & Split(myRng.Address(external:=True), "]")(1)
SolverOk SetCell:=SetAddress, MaxMinVal:=3, ValueOf:=1, ByChange:=ChngAddress, Engine:=1
SolverSolve UserFinish:=True
Set myRng = Nothing
End Sub
这应该可以防止Solver正在做的事与您在调用例程中正在做的事情之间的互动。
设置Application.Calculation = xlCalculationManual
对你没有任何帮助。求解器要求计算模式是自动的并按此方式设置。如果你有不稳定的公式(例如使用RAND()
,NOW()
或RANDBETWEEN()
等),你需要做其他一些技巧。
已更新 - 有关更改活动工作表的问题
我能够强迫Solver认识到SetCell
和ByChange
地址位于活动工作表以外的工作表上(非常困难),并且它产生了以下错误...
这使我们回到在运行解算器之前激活包含解算器问题的工作表。以下内容将保存旧的活动工作表,并重新激活它。
Sub SolveItOnce()
Dim SetRng As Range, ChngRng As Range
Dim mySht As Worksheet
Set mySht = ActiveSheet
Worksheets("P2 Sample").Activate
Set SetRng = Worksheets("P2 Sample").Range("Output")
Set ChngRng = Worksheets("P2 Sample").Range("Input")
SolverOk SetCell:=SetRng.Address, MaxMinVal:=3, ValueOf:=1, ByChange:=ChngRng.Address, Engine:=1
SolverSolve UserFinish:=True
mySht.Activate
Set SetRng = Nothing
Set ChngRng = Nothing
Set mySht = Nothing
End Sub