Is there a Ribbon Menu Tab Change Event in Microsoft VBA?

Bryce Bassett
Bryce Bassett used Ask the Experts™
on
I have developed a Global Template in Microsoft Word, a .dotm that sits in the user's AppData\…\Word\STARTUP folder, so it gets loaded every time the user launches MS Word.  The .dotm creates a custom tab in the Word ribbon menu, a toolbar containing numerous automation macro buttons.

I need to do certain checks each time they use the global template, such as making sure they have the latest version, etc.  I am currently triggering these checks by way of the RibbonOnLoad event.  Problem is the ribbon loads when the user first launches the Word application.  

I would rather trigger these checks only when the user switches to my custom tab. Is there a Word VBA Event that fires when the user changes to a certain ribbon menu tab?

My research suggests there is no such event.  But I want to make sure.  If not, is there a workaround to create this same functionality, so I don't have to call the checks at the beginning of every single macro?

Thanks!
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
ste5anSenior Developer

Commented:
There is no such event.

If not, is there a workaround to create this same functionality, so I don't have to call the checks at the beginning of every single macro?
Sure, simply use a private Boolean variable. Set it to True after you run your checks. And add a guard clause to each method. This allows you to run your macros be invoking them also by Run Macro dialog or the command line.

When you really want to use an event, than add a getVisible or getEnabled event handler to your groups in ribbon XML and your code behind. They are called the first time a group is shown after the start or an invalidate call affecting the group.
Bryce BassettFreelance VBA programmer

Author

Commented:
Thanks for your reply, Ste5an.  However, I do not understand how your suggestion solves my problem.

If I put a getVisible event handler in a ribbon XML group, that event is triggered when the global template first loads, which happens when Word is launched.  This is what I am trying to avoid.  I don't want to run my checks until the user switches to my custom tab or runs one of my macros.

Perhaps I have misunderstood you.   Can you please provide more details?

Thanks
ste5anSenior Developer

Commented:
Test it, cause it is only triggered, when your tab is the first time selected. You can trigger it later again by invalidating the group.

The question is: How often do you want to call those checks.

When you want to run it once, then the event is a viable way. If you need to call it more often, then you need to control it by code in all macros itself.
PMI ACP® Project Management

Prepare for the PMI Agile Certified Practitioner (PMI-ACP)® exam, which formally recognizes your knowledge of agile principles and your skill with agile techniques.

Bryce BassettFreelance VBA programmer

Author

Commented:
My checks need to be triggered only one time when the tab is first selected.  

How do I trigger the checks when the tab is first selected?   You say the event is a viable way, but there is no "change tab" event.  So I still do not have an answer to my original question.

The only way I can figure out is to put a line at the beginning of each macro procedure, something like this:  
If startupchecked = false then call startupchecks

Open in new window

1. Determine whether the checks been performed this session.
2. If not, perform the checks, and end by setting a public variable showing the checks have been done.  So they won't be repeated as long as the current session of Word remains open.  

Is there a better approach?
Senior Developer
Commented:
How do I trigger the checks when the tab is first selected?   You say the event is a viable way, but there is no "change tab" event.  So I still do not have an answer to my original question.
Correct, thus you should use the getVisible event of the first group in your tab as I already wrote.

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"  onLoad="RibbonOnLoad" loadImage="RibbonLoadImage">
  <ribbon>
    <tabs>
      <tab id="TAB_ID" label="TAB_LABEL">
        <group id="GROUP_ID" label="GROUP_LABEL" getVisible="RibbonGetVisible">
          <button id="BUTTON_ID" size="large" label="BUTTON_LABEL" image="airplane.ico" onAction="RibbonOnAction" getVisible="RibbonGetVisible" />
        </group>
      </tab>
    </tabs>
    <contextualTabs>
      <tabSet idMso="TabSetFormDatasheet" visible="false" />
    </contextualTabs>
  </ribbon>
</customUI>

Open in new window

with

Option Explicit

Private m_Initialized As Boolean
Private m_Ribbon As IRibbonUI

Public Sub RibbonGetVisible(AControl As IRibbonControl, ByRef AVisible)

  On Local Error Resume Next

  If Not m_Initialized Then
    ' Run initialization code.
    m_Initialized = True
  End If

  AVisible = True

End Sub

Public Sub RibbonOnLoad(ARibbon As IRibbonUI)

  On Local Error Resume Next

  m_Initialized = False
  Set m_Ribbon = ARibbon

End Sub

Open in new window


The only way I can figure out is to put a line at the beginning of each macro procedure, something like this [..]

As I already wrote:
Sure, simply use a private Boolean variable. Set it to True after you run your checks. And add a guard clause to each method. This allows you to run your macros be invoking them also by Run Macro dialog or the command line.

Option Explicit

Public Sub YourMacro()

  On Local Error Resume Next
  
  Initialize
  
  ' Macro goes here.

End Sub

Open in new window

with

Option Explicit

Private m_Initialized As Boolean

Public Function Initialize() As Boolean

  On Local Error Resume Next

  Initialize = False
  If Not m_Initialized Then
    InternalInitialize
    m_Initialized = True
    Initialize = True
  End If

End Function

Private Sub InternalInitialize()

  'Init code goes here.

End Sub

Open in new window

Bryce BassettFreelance VBA programmer

Author

Commented:
It works very well!

Thanks for the detail and the code.  I could not have figured it out without your help.  

I will post my sample global template (save in Word STARTUP directory in the AppData area) for others who may be looking for the same solution.
Bryce BassettFreelance VBA programmer

Author

Commented:
Here is my sample global template implementing Ste5an's suggested code.
TriggerTest.dotm

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial