Skip to content

Using SolverWrapper Events

Mike 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