VBA不添加元素到Solver模型

我之前有一个问题,解决scheme没有通过VBA添加二进制约束模型…我(大多数)认为这一个。 但现在我有一个新的问题。 首先,让我发表违规代码的相关部分。 我应该注意到这是在Excel 2007中运行。

'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 

这里的基本思想是遍历工作表并查看数据(将从执行到执行),并build立适当的模型。

stringby_change_string包含所有变化variables的单元格地址,它们都是二进制的。 因此,当代码检查电子表格的每一行时,它会确定该行上的哪些单元格可供模型考虑并将其附加到string中。

解决日益增长的by_change_string的多个调用是一个尝试解决二进制约束未被添加到模型的早期问题。 所有的<=约束是,但不是二进制。 看来你不能约束一个variables是二进制的,直到它被添加到模型中。 在构造by_change_string的循环完成之后,曾经只有一个solverok语句,但是当我这样做时,我得到了所有的<=约束,而没有任何二进制的约束。

当这个代码在我的testing表上运行时,结果模型应该有136个决策variables(通过改变单元格)。 我已经检查了,而且by_change_string其实有136个地址。 但是当我查看求解器对话框时,只有前41个。我已经在debugging模式下执行了整个执行过程,并且在每次迭代后都看到它调用solverok,但由于某种原因,只有前41个变化单元在那里。 对于出现问题的那一行数据没有什么特别之处……它不像是某个select案例的第一个实例或其他东西…

当求解器运行在这个缩写模型上时,它返回一个垃圾解决scheme,它说是最优的。 基本上它保持一切都一样,所以最终目标函数的价值是一样的开始。

所以然后我尝试了其他的东西…你会注意到在底部有一个注释掉的代码块:

 '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 

这里的想法是通过让所有的解决scheme和解决scheme陈述脱离select案例来使事情变得更有效率。 通过等待最后的solverok语句之后,所有的variables现在都在模型中,所以你应该简单地通过by_change_string并使每个variables成为一个二进制variables。 这样,你只需要一个solverok语句,你可以摆脱所有的select案例中的所有solveradd。 所以我在select的案例中评论了所有的solverok和solveradd,并且再次运行macros。 求解器没有输出。 运行后查看求解器对话框时,目标单元格和通过更改单元格字段都为空。 就好像最后的解决scheme声明从未运行过。

所以我试着去掉所有的solverok的注释,但是把二进制variables的solveradd留给注释掉了。 我只能回到前41个决策variables。 设置二进制约束的循环完成了它的工作,但是solveradd没有将variables存入模型。

我很困难在这一点上。 有任何想法吗?

正如我所设想的:

求解器在“更改单元格”参数中只允许最多255个字符。 如果您不相信我,请尝试手动添加您想要的单元格。 你将无法做到这一点。

你可以通过求解器的最大不连续范围是51(假设每个组只有1格,格式像$A$1,个字母是1个数字2美元符号和1个逗号)。 如果您尝试手动添加更多,它将删除所有以前的select。 大概用代码来做这件事,只要你遇到了长度限制就忽略了一切。

说实话,我从来没有使用过解算器,也不知道如何通过代码来访问它。 无论如何,你正试图让它做一些无能为力的事情。

现在,而不是只告诉你,它不会工作,这是一个可能的(但我认为令人讨厌)的工作。 如果我不得不做你正在做的事情,我会试试这个。 将重要的值复制到工作簿中的另一个位置,并将它们相邻放置,以便可以将它们作为连续范围传递。 一旦求解器运行,把你的值放回应该在的位置。

编辑: 这个有限的解决scheme的文档可能会稍微过时,但它声明以下内容:

模型决策variablesinput到“更改单元格”编辑框中。 Excel允许input一个所谓的多重select,它由多达16个以逗号分隔的范围(矩形,行或列,或单个单元格)组成。

这意味着解算器只能有16个不连续的范围,并期望它能够工作。

丹尼尔·库克似乎是正确的问题的原因。 我会build议一个不同的解决方法。 创build一个包含所有非连续范围的命名范围,并将by_change_string设置为表示该命名范围的string。