问题
I am trying to find a maximum return for a simple portfolio using Solver. Using Solver in the worksheet directly works sensibly, however it does not when the commands are set in VBA. Instead (as you can see from the screengrab)it ignores one of the constraints (that the sum of weights calculated in T10 should =1). Interestingly it works fine if I change the third line to say:
SolverAdd CellRef:="$T$10", Relation:=2, FormulaText:="100"
Or any other integer other than "1". (It may also be ignoring the other constraint but I cannot check this). The table looks like this:
And my code is:
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
Any suggestions gratefully welcomed!
回答1:
Found a work around for the bug. For the flag "FormulaText:=1". instead of using 1, use a reference to any cell with the value 1 instead.
I.e., Change "FormulaText:=1" to "FormulaText:=$H$5" where $H$5's value is 1
回答2:
I think there is a bug here whenever the value is exactly 1. Other postings state that the above solution (putting the value into a cell) is unreliable. I have found it does not work a my code always refers to a cell which holds the constraint limit. My (crude) solution is to shift the limit value by 1 part in 10^12 or lower in the appropriate direction which sort of makes the constraint into a < or > rather than a <= or >=. So rather than:
SolverAdd CellRef:=Range("SolverParam").Address, Relation:=3, _ FormulaText:=Range("SolverConstraint").value
Use:
SolverAdd CellRef:=Range("SolverParam").Address, Relation:=3, _ FormulaText:=Range("SolverConstraint").value + Abs(Range("SolverConstraint").value) * 1e-12
And use the opposite sign for Relation:=1
In this trivial example SolverParam is a single cell parameter to be adjusted and SolverConstraint is a single cell lower bound.
This is the only consistent approach I can foresee to have a uniform handling of all values
On further looking I found another solution from the web
FormulaText:="=" & Range("SolverConstraint").value
Seems to work reliably
回答3:
I had the exact same issue. I solved it in the following way: Just type FormulaText:=1 without the quotes for 1.
来源:https://stackoverflow.com/questions/15620177/excel-solver-ignoring-constraint-in-vba