Excel VBA不向解算器模型添加图元

Excel VBA不向解算器模型添加图元,excel,vba,solver,Excel,Vba,Solver,我之前遇到过一个问题,就是解算器没有通过VBA将二进制约束添加到模型中……我(大部分)已经解决了这个问题。但现在我有了一个新问题。首先,让我发布违规代码的相关部分。我应该注意到这是在Excel2007中运行的 'build string of ByChange cells and set up cascading constraints by_change_string = "" For i = 1 To j - 1 If Len(by_change_string) > 0 Th

我之前遇到过一个问题,就是解算器没有通过VBA将二进制约束添加到模型中……我(大部分)已经解决了这个问题。但现在我有了一个新问题。首先,让我发布违规代码的相关部分。我应该注意到这是在Excel2007中运行的

'build string of ByChange cells and set up cascading constraints
by_change_string = ""
For i = 1 To j - 1

    If Len(by_change_string) > 0 Then                   'there are already some elements in the string, so we might start with a comma
        If Not (Right(by_change_string, 1) = ",") Then  'make sure the last character isn't already a comma
            by_change_string = by_change_string & ","
        End If
    End If

    current_status = Sheets("Buyback Risk Area").Range("C1").Offset(i).Value
    Select Case current_status
        Case "Y"                'risk area is currently yellow, so green transition is available
            by_change_string = by_change_string & "$E$" & i + 1
            solverok setcell:="$B$" & j + 4, MaxMinVal:=2, ValueOf:="0", ByChange:=by_change_string

            'add binary constraints
            solveradd cellref:="$E$" & i + 1, relation:=5, formulatext:="binary"
        Case "O"                'risk area is currently orange, so green and yellow transitions are available
            by_change_string = by_change_string & "$E$" & i + 1 & ",$G$" & i + 1
            solverok setcell:="$B$" & j + 4, MaxMinVal:=2, ValueOf:="0", ByChange:=by_change_string

            'add cascading constraints
            solveradd cellref:="$E$" & i + 1, relation:=1, formulatext:="$G$" & i + 1 'says E <= G, which means you can't select green unless you've already selected yellow

            'add binary constraints
            solveradd cellref:="$E$" & i + 1, relation:=5, formulatext:="binary"'                solveradd cellref:="$G$" & i + 1, relation:=5, formulatext:="binary"
        Case "R"                'risk area is currently red, so green, yellow, and orange transitions are available
            by_change_string = by_change_string & "$E$" & i + 1 & ",$G$" & i + 1 & ",$I$" & i + 1
            'solverok setcell:="$B$" & j + 4, MaxMinVal:=2, ValueOf:="0", ByChange:=by_change_string

            'add cascading constraints
            solveradd cellref:="$E$" & i + 1, relation:=1, formulatext:="$G$" & i + 1 'says E <= G, which means you can't select green unless you've already selected yellow
            solveradd cellref:="$G$" & i + 1, relation:=1, formulatext:="$I$" & i + 1 'says G <= I, which means you can't select yellow unless you've already selected orange

            'add binary constraints
            solveradd cellref:="$E$" & i + 1, relation:=5, formulatext:="binary"
            solveradd cellref:="$G$" & i + 1, relation:=5, formulatext:="binary"
            solveradd cellref:="$I$" & i + 1, relation:=5, formulatext:="binary"
        Case "B"                'risk area is black, so green, yellow, orange and red transitions are avaailable
            by_change_string = by_change_string & "$E$" & i + 1 & ",$G$" & i + 1 & ",$I$" & i + 1 & ",$K$" & i + 1
            solverok setcell:="$B$" & j + 4, MaxMinVal:=2, ValueOf:="0", ByChange:=by_change_string

            'add cascading constraints
            solveradd cellref:="$E$" & i + 1, relation:=1, formulatext:="$G$" & i + 1 'says E <= G, which means you can't select green unless you've already selected yellow
            solveradd cellref:="$G$" & i + 1, relation:=1, formulatext:="$I$" & i + 1 'says G <= I, which means you can't select yellow unless you've already selected orange
            solveradd cellref:="$I$" & i + 1, relation:=1, formulatext:="$K$" & i + 1 'says K <= M, which means you can't select orange unless you've already selected red

            'add binary constraints
            solveradd cellref:="$E$" & i + 1, relation:=5, formulatext:="binary"
            solveradd cellref:="$G$" & i + 1, relation:=5, formulatext:="binary"
            solveradd cellref:="$I$" & i + 1, relation:=5, formulatext:="binary"
            solveradd cellref:="$K$" & i + 1, relation:=5, formulatext:="binary"
    End Select
Next i

'buyback amount constraint
solveradd cellref:="$O$" & j + 1, relation:=1, formulatext:="$B$" & j + 2

'set target cell
solverok setcell:="$B$" & j + 4, MaxMinVal:=2, ValueOf:="0", ByChange:=by_change_string

'set binary constraints
'binary_array = Split(by_change_string, ",")
'For i = 0 To UBound(binary_array)
'    solveradd cellref:=Range(binary_array(i)), relation:=5, formulatext:="binary"
'Next i


Application.ScreenUpdating = True

SolverSolve userFinish:=False
这里的想法是通过从选择的案例中获取所有那些solverok和solverad语句来提高效率。等到最后一个solverok语句之后,所有变量现在都在模型中,因此您应该能够单步遍历By_change_字符串,并将其中的每一个变为二进制变量。这样,您只需要一个SolverRok语句,就可以在选定的情况下删除所有solveradd语句。因此,我注释掉了所选案例中的所有SolverRok和SolverRadd,然后再次运行宏。我没有从解算器得到任何输出。运行后查看“解算器”对话框时,“目标单元格”和“通过更改单元格”字段均为空。这就好像最后的solverok声明从未运行过一样

然后我尝试取消对所有solverok的注释,但将solveradd留给注释掉的二进制变量。我返回到只获取前41个决策变量。设置二进制约束的循环完成了它的工作,但是solverad没有将变量输入到模型中

在这一点上我几乎被难住了。有什么想法吗?

正如我所想:

通过更改单元格参数,解算器最多只允许255个字符。如果您不相信,请尝试手动添加所需的单元格。你将无法做到这一点

可以传递解算器的最大非连续范围为51(假设每个组只有1个单元格,格式类似于
$A$1,
带有1个字母1个数字2个美元符号和1个逗号)。如果您尝试手动添加更多,它将删除以前的所有选择。假设在代码中执行此操作时,一旦满足长度约束,就会忽略所有内容

老实说,我从未使用过解算器,也不知道如何通过代码访问它。不管怎样,你试图让它做一些它做不到的事情

现在,与其只是告诉你这行不通,不如说这里有一个可能的(但在我看来是令人讨厌的)解决办法。如果我必须做你正在做的事,我会这么做。将重要的值复制到工作簿中的另一个位置,并将它们彼此相邻设置,以便可以将它们作为连续范围传递。解算器运行后,将值放回其应位于的位置

编辑:可能有点过时,但说明如下:

模型决策变量通过更改编辑单元格输入到中 盒子。Excel允许用户输入所谓的多重选择,即 最多由16个范围(矩形、行或列或单个区域)组成 单元格)用逗号分隔


这意味着您只能对解算器使用16个非连续范围,并且希望它能够正常工作。

Daniel Cook关于问题原因的看法似乎是正确的。不过我会提出一个不同的解决办法。创建一个包含所有非连续范围的命名范围,并通过“更改”字符串将其设置为表示该命名范围的字符串。

我想在这些答案中添加以下内容:

  • 使用代码超过最大值会在模型中留下一个空的Bychange区域
  • 命名一个范围并不能解决问题,因为解算器会立即用其常用语言对其进行翻译,并删除窗口中无法容纳的最后一个范围
  • 来源:我刚刚用excel 2013尝试了这些解决方案

    'set binary constraints
    'binary_array = Split(by_change_string, ",")
    'For i = 0 To UBound(binary_array)
    '    solveradd cellref:=Range(binary_array(i)), relation:=5, formulatext:="binary"
    'Next i