Option Explicit
'''Separate function to find the last used row in a defined column letter
Private Function FindLastRow(ColumnToCheck As String) As Long
FindLastRow = Range(ColumnToCheck & Rows.Count).End(xlUp).Row
End Function
Sub Optimise()
'The starting row - this would be better done automatically in code but I don't know your sheet layout
Const lSTARTROW As Long = 10
Dim lEndRow As Long
Dim i As Long
Const GUESS_E As String = "50%", GUESS_F As String = "30%", GUESS_G As String = "20%"
Application.ScreenUpdating = False
lEndRow = FindLastRow("D")
For i = lSTARTROW To lEndRow
'set initial values programmatically
ActiveSheet.Cells(i, 5).FormulaR1C1 = GUESS_E
ActiveSheet.Cells(i, 6).FormulaR1C1 = GUESS_F
ActiveSheet.Cells(i, 7).FormulaR1C1 = GUESS_G
'Solver section
SolverReset
'Constraints
SolverAdd CellRef:=Cells(i, 3), Relation:=2, FormulaText:=Cells(i, 2)
SolverAdd CellRef:=Cells(i, 5), Relation:=3, FormulaText:="0"
SolverAdd CellRef:=Cells(i, 6), Relation:=3, FormulaText:="0"
SolverAdd CellRef:=Cells(i, 7), Relation:=3, FormulaText:="0"
SolverAdd CellRef:=Cells(i, 8), Relation:=2, FormulaText:="1"
'Run Solver to minimise D by chaging E,F,G columns
SolverOk SetCell:=Cells(i, 4), MaxMinVal:=2, ValueOf:=0, ByChange:=Range(Cells(i, 5), Cells(i, 7)), Engine:=1, EngineDesc:="GRG Nonlinear"
SolverSolve True
Next i
Application.ScreenUpdating = True
End Sub