在另一张纸上处理VBA Solver时出现奇怪的错误

时间:2016-04-30 21:49:18

标签: excel vba excel-vba

当我通过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

1 个答案:

答案 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时,SetCellByChange的输入需要是字符串,而不是范围。此外,为了确保解算器引用正确的工作表,最好使用工作表名称“完全限定”字符串中的范围。我建议您的代码看起来像这样(已编译但未经过测试)......

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认识到SetCellByChange地址位于活动工作表以外的工作表上(非常困难),并且它产生了以下错误...

enter image description here

enter image description here

这使我们回到在运行解算器之前激活包含解算器问题的工作表。以下内容将保存旧的活动工作表,并重新激活它。

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
相关问题