我正在尝试使用求解器找到简单投资组合的最大回报。在工作表中直接使用 Solver 可以正常工作,但在 VBA 中设置命令时则不然。相反(正如您从屏幕截图中看到的)它忽略了其中一个约束(T10 中计算的权重总和应 = 1)。有趣的是,如果我将第三行改为:
,效果很好SolverAdd CellRef:="$T$10", Relation:=2, FormulaText:="100"
或“1”以外的任何其他整数。
(它也可能忽略其他约束,但我无法检查这一点)。
该表如下所示:
我的代码是:
Sub FindRange()
SolverReset
SolverOk SetCell:="$T$7", MaxMinVal:=1, ValueOf:="0", ByChange:="$O$10:$R$10"
SolverAdd CellRef:="$T$10", Relation:=2, FormulaText:="1"
SolverAdd CellRef:="$O$10:$R$10", Relation:=3, FormulaText:="0"
SolverSolve UserFinish:=True
SolverFinish KeepFinal:=1
Range("T9").Value = Range("T7").Value
End Sub
任何建议都非常欢迎!
找到了解决该错误的方法。对于标志“FormulaText:=1”。不要使用 1,而是使用对任何值为 1 的单元格的引用。
即,将“FormulaText:=1”更改为“FormulaText:=$H$5”,其中 $H$5 的值为 1
我认为只要该值恰好为 1,就会出现错误。其他帖子指出上述解决方案(将值放入单元格中)不可靠。 我发现它不起作用,因为我的代码总是引用一个包含约束限制的单元格。 我的(粗略)解决方案是将极限值在适当的方向上移动 10^12 或更低的 1 部分,这使得约束变成 < or > 而不是 <= or >=。 所以而不是:
SolverAdd CellRef:=Range("SolverParam").地址,关系:=3, _ FormulaText:=Range("SolverConstraint").value
用途:
SolverAdd CellRef:=Range("SolverParam").地址,关系:=3, _ FormulaText:=Range("SolverConstraint").value + Abs(范围("SolverConstraint").value) * 1e-12
并使用相反的符号表示关系:=1
在这个简单的示例中,SolverParam 是要调整的单个单元格参数,SolverConstraint 是单个单元格下界。
这是我可以预见的唯一一致的方法,可以统一处理所有值
进一步查看,我从网上找到了另一个解决方案
FormulaText:="= & Range("SolverConstraint").value
看起来工作可靠
我也遇到了完全相同的问题。我通过以下方式解决了它: 只需输入 FormulaText:=1,不带 1 的引号。
按照sevenkul的建议添加“=”对我有用。
SolverAdd CellRef:=“$F$13”,关系:=2,FormulaText:=“=1”
在此之前,我还在求解器窗口中得到了缺失的约束。从工作表手动添加约束效果很好,但在运行 VBA 代码后不会显示(由于 SolverReset 调用)。我还认为问题不限于值 1。我也尝试过 2 并得到了类似的结果。
奇怪的是,在运行建议的修复一次后,我不再需要 FormulaText 中额外的“=”。我关闭并重新打开工作簿,不需要解决方法。运行一次似乎就可以了。不确定是否需要在代码中使用求解器在每个新工作簿上完成此操作。