Reputation: 1
I created an addin for Excel I need to access in certain workbooks, which I can identify by some criteria.
There is a ribbon tab that makes access easy. When I (or other users) open a new workbook or a workbook that doesn't fulfill the criteria, the ribbon tab should not be visible, but still be visible when I switch back to the correct workbook.
If I understand right, this is automatic if the ribbon tab is in an xlsm, but I need to have it in an external XLAM.
The XLAM has XML code like the below (some more, but this is the essential), and I had hoped that the getVisible="MyGetVisible" on the tab line should be able to function as the on/off switch when it was set to True (for the workbook where the ribbon tab should show) and False (for the others) and the ribbon was invalidated.
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
onLoad="CallbackOnLoad">
<ribbon>
<tabs>
<tab id="MyTab" label="My Custom tab" insertBeforeMso="TabHome" getVisible="MyGetVisible">
<group idMso="GroupClipboard" />
<group id="MyGroup1" label="Sheet Navigation">
<dropDown id="MyDD1" label="Data Sheets" showLabel="false" imageMso="TextAlignGallery" getVisible="MyGetVisible2" getItemCount="MyGetItemCount" getItemID="MyGetItemID" sizeString="xxxxxxxxxx" getItemLabel="MyGetItemLabel" getSelectedItemID="MyGetSelectedItemID" onAction="MyOnAction"/>
</group>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
VBA code for MyGetVisible
Public Sub GetVisible(control As IRibbonControl, ByRef visible)
visible = (ActiveWorkbook.name = "MyWBwhereTheRibbonTabShouldShow.xlsm")
End Sub
My RibRefresh shows some of my tests, with DoEvents and Wait. The Ribbon ID is stored and that is not the problem. (Although it seemed safer to store the ID in a named cell in the xlam than to store it in a created name not referring to a range.)
Public Sub RibRefresh()
Debug.Print ActiveWorkbook.name
If MyRibbon Is Nothing Then RibRetrieve
DoEvents
Application.Wait Now + 0.00001
MyRibbon.Invalidate
DoEvents
If err.Number > 0 Then
MsgBox "The Ribbon-pointer is lost, save-close & restart workbook instead"
err.Clear
End If
End Sub
Microsoft® Excel® for Microsoft 365 MSO (Version 2208 Build 16.0.15601.20526) 32-bit
Upvotes: 0
Views: 527
Reputation: 1
I finally managed to get it to work as I wanted, and what I did was to make sure the GetVisible macro for the tab wasn't called "GetVisible" but a different name like I suggested above but didn't do: "MyGetVisible", I don't know if it gets confused or it was multiple things happening.
I also changed the code in ThisWorkbook of the one where I wanted the xlam's tab to be visible, since the execution sequence between the tab's callback and the Workbook_activate wasn't what I expected. So I added a test to make sure it didn't execute before MyXLAM had a value (which it gets in the tab's Callback)
Option Explicit
Dim bHasOpened As Boolean
Private Sub Workbook_Activate()
If bHasOpened Then Application.Run MyXLAM & "RibRefresh"
End Sub
Private Sub Workbook_Deactivate()
bHasOpened = True
Application.Run MyXLAM & "RibRefresh"
End Sub
Thanks for the help!
Upvotes: 0
Reputation: 49455
The logic in the RibRefresh
sub is overcomplicated with DoEvents
and Wait
etc. The only possible place where you can retrieve the ribbon object instance (to be precise, an instance of the IRibbonUI
interface) is the onLoad
callback where it is passed as a parameter. You need to save/store it in the local object for further usage. For example, here is how the declaration looks in the ribbon XML:
<customUI … OnLoad="MyAddinInitialize" …>
and the callback:
Dim MyRibbon As IRibbonUI
Sub MyAddInInitialize(Ribbon As IRibbonUI)
Set MyRibbon = Ribbon
End Sub
Then where required you may call the Invalidate
method to get your callbacks invoked anew:
Sub myFunction()
MyRibbon.Invalidate() ' Invalidates the caches of all of this add-in's controls
End Sub
Note, if an add-in writer implements the getVisible
callback procedure for a control/tab, the function is called once, the state loads, and then if the state needs to be updated, the cached state is used instead of recalling the procedure. This process remains in place until the add-in signals that the cached values are invalid by using the Invalidate
method, at which time, the callback procedure is again called and the return response is cached.
It seems you need to handle scenarious where the workbook is opened, activated, closed and etc. to keep the ribbon UI up to date by calling the Invalidate
method of the IRibbonUI
interface.
Upvotes: 2