Skip to content

Using SolverWrapper Events

Michael Waite edited this page Mar 15, 2026 · 2 revisions

An arguably more powerful alternative to the callback function for monitoring optimization progress is through the use of SolverWrapper native events, albeit at the cost of a little more work. There are three native events: BeforeSolve which fires once before optimization begins, ShowTrial that fires on each trial solution, and AfterSolve which fires after optimization is completed. Below is an example of how to set up your own event class and connect that to SolverWrapper.

In order for SolverWrapper events to be triggered, the EnableEvents property of the SolvSolver class must be set to True, and a user-created event sink instantiated, as in the following example:

    'enable SolverWrapper native events
    oProblem.Solver.EnableEvents = True

    If oProblem.Solver.EnableEvents Then
        'connect-up user-created events processing class
        Dim eventSink As SolverEventSink
        Set eventSink = New SolverEventSink
        Set eventSink.Problem = oProblem
    End If
    
    oProblem.SolveIt

In order then to process the SolverWrapper events, the user should create their own event sink class, such as the example below:

'Class Name: SolverEventSink (user preference)
'@ModuleDescription "This is an example of a user-written class to process events triggered by the SolvProblem class."
'@folder("SolverWrapper.Examples")

'The EnableEvents property of the SolvSolver class must be set to True to activate SolverWrapper events

Private WithEvents oProblem As SolvProblem

Private Sub oProblem_ShowTrial(ByVal reason As Long, ByVal trialNum As Long, stopSolver As Boolean)
    'this event is triggered for any one of the reasons below
    Dim i As Long
    
    Debug.Print "Trial number: " & trialNum
    Debug.Print "Objective: " & oProblem.Objective.CellRange.value
    
    For i = 1 To oProblem.DecisionVars.Count
        Debug.Print oProblem.DecisionVars.CellRange(i).Address, oProblem.DecisionVars.CellRange(i).value
    Next i
    
    Debug.Print "Constraints Satisfied? " & oProblem.Constraints.AreSatisfied
    
    'decide whether to stop solver based on the reason for the event trigger
    Select Case reason
        Case SlvCallbackReason.slvShowIterations 'new iteration has completed or user hit esc key
            stopSolver = False
        Case SlvCallbackReason.slvMaxTimeLimit
            stopSolver = True 'if set to True then solver is stopped!
        Case SlvCallbackReason.slvMaxIterationsLimit
            stopSolver = False
        Case SlvCallbackReason.slvMaxSubproblemsLimit
            stopSolver = False
        Case SlvCallbackReason.slvMaxSolutionsLimit
            stopSolver = False
    End Select
End Sub

Private Sub oProblem_BeforeSolve(stopSolver As Boolean)
    Debug.Print "Solver started on Worksheet: " & oProblem.SolverSheet.Name
End Sub

Private Sub oProblem_AfterSolve(ByVal returnMsgCode As Long, ByVal trialNum As Long)
    Debug.Print "Solver completed with iterations= " & trialNum
    Debug.Print "Solver return code= " & oProblem.Solver.MsgCodeToString(returnMsgCode)
End Sub

Public Property Set Problem(obj As SolvProblem)
    Set oProblem = obj
End Property

Private Sub Class_Terminate()
    Set oProblem = Nothing
    Debug.Print "terminating SolvEventSink"
End Sub

Clone this wiki locally