Search code examples
vbams-wordribbonx

How to disable ribbon while VBA code is running


I need to cancel button clicks on a Custom Ribbon if code is already running.

The problem: although I can disable the button, clicks are still 'registered' and even though disabled, the corresponding code runs once for each button click.

Public Sub OnActionButton(control As IRibbonControl)

    ' The following approach fails to prevent code from running
    If Not globalEnabled Then Exit Sub

    ' The following approach fails to prevent code from running
    Dim goodToGo as Boolean
    GetEnabled control, goodToGo
    If Not goodToGo Then Exit Sub


    ' *********************************************************
    ' Code Below Here Should NOT Run If Button Was Clicked 
    ' While globalEnabled = False (i.e. code already running)
    ' *********************************************************

    ' Disable the Ribbon
    globalEnabled = False
    RibbonInvalidate

    Select Case control.id
        Case "btnID"
            ' doSomething
    End Select

    ' Re-enable the ribbon
    globalEnabled = True
    RibbonInvalidate

End Sub

Edit: For what its worth, this is how I disable the button:

Public Sub GetEnabled(control As IRibbonControl, ByRef enabled)
' Called by RibbonInvalidate
    Select Case control.id
        Case "btnID"
            enabled = globalEnabled 
    End Select 
End Sub

I can imagine that the first click runs as expected, the second click (which is made while the code corresponding to the first click is running) is 'queued' until the first click is completed. At that time globalEnabled is True again so the checks are ineffective.

I guess I could hide the custom ribbon tab (or replace it with a dummy tab) - but is that really necessary?

Is there an elegant way to cancel a button press?


Edit:

I could add a bunch of doEvents to the code, but slows things down too much.

Edit2:

If I display a message box during code execution then, for some reason, it seems that things work as expected...

In fact... if I display a message box then I don't even need the early exit logic - so weird!


Solution

  • This works, main thing was adding doEvents (or a message box) at the end.

    Public Sub OnActionButton(control As IRibbonControl)
    
        ' Disable the Ribbon
        globalEnabled = False
        RibbonInvalidate
    
        Select Case control.id
            Case "btnID"
                ' doSomething
        End Select
    
        ' Re-enable the ribbon
        doEvents                     ' <-- Adding this fixed the issue for me
        ' msgbox "finished"          ' <-- also works, but pretty annoying ;-)
        globalEnabled = True
        RibbonInvalidate
    
    End Sub