I have experienced the following situation in two totally different Windows environments (home and work) on Office 365 (Word 11929.20254) and Word 2016, using a range of documents and templates which use VBA and customUI.xml to display a custom ribbon:
If I run the above situation in Excel or PowerPoint with spreadsheet or presentation files with the exact same custom ribbon as I used in Word above, step 5 doesn't apply; the ribbon works properly, onLoad runs, and so on.
Why does the Word ribbon appear to be deficient in a way in which other Office ribbons are not? Would developing an add-in rather than VBA and customUI.xml resolve or bypass this issue?
Edit:
A bare example of a custom ribbon and associated VBA follows. Put these in the customUI.xml and VBA of a Word document and use this as the second Word document, mentioned in steps 2 to 5.
Put the ribbon and VBA below into an Excel spreadsheet then run through steps 1 to 5 above, except using Excel spreadsheets instead of Word documents. Upon reaching step 5, the ribbon seems fine, unlike in Word.
customUI.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="modRibbon.CustomUI_OnLoad">
<ribbon>
<tabs>
<tab id="tabCustom" label="Custom" insertBeforeMso="TabHome">
<group id="grpCustom1" imageMso="EditDocument" label="Custom group 1">
<button id="btnA" size="large" label="Aa" imageMso="EditDocument" onAction="modRibbon.btn1A_OnAction" screentip="Aa" supertip="A button."/>
</group>
<group id="grpCustom2" imageMso="EditBusinessCard" label="Custom group 2">
<button id="btnB" size="large" label="Bb" imageMso="EditBusinessCard" onAction="modRibbon.btn2B_OnAction" screentip="Bb" supertip="Another button."/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
modRibbon VBA module:
'Callback for customUI.onLoad
Sub CustomUI_OnLoad(ribbon As IRibbonUI)
End Sub
'Callback for btnA_onAction
Sub btn1A_OnAction(control As IRibbonControl)
End Sub
'Callback for btnB_onAction
Sub btn2B_OnAction(control As IRibbonControl)
End Sub
I've come up with a solution, which has been very reliable thus far, by adding the following to ThisDocument
:
Private Sub Document_Open()
Application.OnTime Now, "modRibbon.ReloadRibbon"
End Sub
and adding the following to the modRibbon VBA module (in OP):
Sub ReloadRibbon()
With Application.CommandBars
.Add "barRibbonRefresher", msoBarTop, False, True 'Adds a dummy bar
.Item("barRibbonRefresher").Delete 'Deletes the dummy bar above, which appears to force the custom UI, including the custom ribbon, to (re)load
End With
End Sub
This solution:
It's important to note that:
With
block in Document_Open()
won't suffice; OnTime
must be used;OnLoad
callback runs when the ribbon reloads, exactly as it does when opening the document.I assume there is something special about CommandBars
, and in particular the .Delete
method, which shocks the ribbon (back) into life, which would be a tad ironic given that the ribbon is supposed to replace CommandBars
, not be dependent on them for tricks to function properly.
Side note: This could also provide a simpler way of restoring the ribbon when its pointer is lost, a fairly common occurrence when VBA encounters errors while executing ribbon methods. A current solution (which also applies to Word) involves storing the pointer somewhere (such as in ThisDocument.Variables
) then restoring it via CopyMemory
. The solution above may be able to simply create the ribbon anew and thus dispense with any such error.