Search code examples
vbams-wordribbonxribbon-control

Toggle buttons that control visibility of other groups and controls


I am trying to include toggle buttons (4) that will toggle groups visible or invisible through tags while also making the other toggle buttons invisible. The reset will make all groups invisible, except for toggle group

The code works without including the toggle buttons.

Toggle 1 controls groups 1 and 5. Toggle 2 controls groups 2 and 6. Toggle 3 controls groups 3 and 7. Toggle 4 controls groups 4 and 8.

I've pared it down for confidentiality. Unfortunately, the ribbon doesn't load.

This is my current xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customUI onLoad="OnStart" xmlns="http://schemas.microsoft.com/office/2009/07/customui">
    <ribbon>
        <tabs>
            <!-- New tab -->
            <tab id="tab1" label="tab1" insertBeforeMso="TabHome">

                <!-- New group - toggle buttons that controls other groups -->
                <group id="GroupToggle" label="Toggle">
                    <toggleButton id="Toggle1" label="Toggle 1" size="large" onAction="onActionToggle" imageMso="_1" tag="Toggle1Main" getVisible="GetVisible" />
                    <toggleButton id="Toggle2" label="Toggle 2" size="large" onAction="onActionToggle" imageMso="_2" tag="Toggle2Main" getVisible="GetVisible" />
                    <toggleButton id="Toggle3" label="Toggle 3" size="large" onAction="onActionToggle" imageMso="_3" tag="Toggle3Main" getVisible="GetVisible" />
                    <toggleButton id="Toggle4" label="Toggle 4" size="large" onAction="onActionToggle" imageMso="_4" tag="Toggle4Main" getVisible="GetVisible" />
                    
                    <!-- This option is always visible -->
                    <button id="ToggleReset" label="Reset" size="large" onAction="onActionToggle" imageMso="R" tag="ToggleMain" />
                </group>

                <!-- Toggle with Toggle1 -->
                <group id="group1" label="Group 1" getVisible="GetVisible" tag="Toggle1">
                    <button id="group1btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>

                <!-- Toggle with Toggle2 -->
                <group id="group2" label="Group 2" getVisible="GetVisible" tag="Toggle2">
                    <button id="group2btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>

                <!-- Toggle with Toggle 3 -->
                <group id="group3" label="Group 3" getVisible="GetVisible" tag="Toggle3">
                    <button id="group3btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>

                <!-- Toggle with Toggle 4 -->
                <group id="group4" label="Group 4" getVisible="GetVisible" tag="Toggle4">
                    <button id="group4btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>

                <!-- Toggle with Toggle 1 -->
                <group id="group5" label="Group 5" getVisible="GetVisible" tag="Toggle1">
                    <button id="group5btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>

                <!-- Toggle with Toggle 2 -->
                <group id="group6" label="Group 6" getVisible="GetVisible" tag="Toggle2">
                    <button id="group6btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>

                <!-- Toggle with Toggle 3 -->
                <group id="group7" label="Group 7" getVisible="GetVisible" tag="Toggle3">
                    <button id="group7btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>

                <!-- Toggle with Toggle 4 -->
                <group id="group8" label="Group 8" getVisible="GetVisible" tag="Toggle4">
                    <button id="group8btn1" label="btn 1" onAction="onActionBtn1" imageMso="A" />
                </group>


            </tab>
        </tabs>
    </ribbon>
</customUI>

This is my current vba

Option Explicit
Dim Ribbon As IRibbonControl
Public MyTag As String

Sub OnStart(ribbon As IRibbonControl)
  Set Ribbon = ribbon
  Call RefreshRibbon(Tag:="*Main")
End Sub

Sub RefreshRibbon(Tag As String)
  MyTag = Tag
  If Ribbon Is Nothing Then
    MsgBox "Error. Reload"
  Else
    Ribbon.Invalidate
  End If
End Sub

Sub GetVisible(control As IRibbonControl, ByRef visible)
  If MyTag = "show" Then
    visible = True
  Else
    If control.Tag Like MyTag Then
      visible = True
    Else
      visible = False
    End If
  End If
End Sub

Sub onActionToggle(control As IRibbonControl, pressed As Boolean)
  Select Case control.ID
    Case "Toggle1"
      Call RefreshRibbon(Tag:="Toggle1*")
    Case "Toggle2"
      Call RefreshRibbon(Tag:="Toggle2*")
    Case "Toggle3"
      Call RefreshRibbon(Tag:="Toggle3*")
    Case "Toggle4"
      Call RefreshRibbon(Tag:="Toggle4*")
    Case "Toggle4"
      Call RefreshRibbon(Tag:="*Main")
  End Select
End Sub

Sub onActionBtn1(control As IRibbonControl)
  Select Case control.ID
    Case "group1btn1"
      'Runs code
    Case "group2btn1"
      'Runs code
    Case "group3btn1"
      'Runs code
    Case "group4btn1"
      'Runs code
    Case "group5btn1"
      'Runs code
    Case "group6btn1"
      'Runs code
    Case "group7btn1"
      'Runs code
    Case "group8btn1"
      'Runs code
End Sub

Solution

  • I'm afraid there are several errors going on here, some more important than others. These changes were all needed to make your code run:

    • No End Select in onActionBtn1.
    • Wrong signature for On Start, must be Sub OnStart(ribbon As IRibbonUI).
    • Wrong type for Ribbon variable, must be IRibbonUI.
    • Wrong name for Ribbon variable - must have different name than ribbon parameter of the OnStart-callback, e.g. MyRibbon.
    • Reset-button is <button> but onAction points to onActionToggle used for a <toggleButton> - must point to onActionBtn1 or similar.
    • You refer to the Reset-button by its Tag name ToggleMain, but the Id is ToggleReset.
    • Also made your variables private, should be as restrictive as possible.

    Putting it all together to make you code work:

    XML

    Change onAction for ToggleReset to point to "onActionBtn1"

    VBA

    Option Explicit
    
    Private MyRibbon As IRibbonUI
    Private MyTag As String
    
    Sub OnStart(ribbon As IRibbonUI)
      Set MyRibbon = ribbon
      Call RefreshRibbon(Tag:="*Main")
    End Sub
    
    Sub RefreshRibbon(Tag As String)
      MyTag = Tag
      If MyRibbon Is Nothing Then
         MsgBox "Error. Reload"
      Else
         MyRibbon.Invalidate
      End If
    End Sub
    
    Sub GetVisible(control As IRibbonControl, ByRef visible)
      If MyTag = "show" Then
         visible = True
      Else
         If control.Tag Like MyTag Then
            visible = True
         Else
            visible = False
         End If
      End If
    End Sub
    
    Sub onActionToggle(control As IRibbonControl, pressed As Boolean)
      Select Case control.ID
         Case "Toggle1"
            Call RefreshRibbon(Tag:="Toggle1*")
         Case "Toggle2"
            Call RefreshRibbon(Tag:="Toggle2*")
         Case "Toggle3"
            Call RefreshRibbon(Tag:="Toggle3*")
         Case "Toggle4"
            Call RefreshRibbon(Tag:="Toggle4*")
      End Select
    End Sub
    
    Sub onActionBtn1(control As IRibbonControl)
      Select Case control.ID
         Case "group1btn1"
            'Runs code
         Case "group2btn1"
            'Runs code
         Case "group3btn1"
            'Runs code
         Case "group4btn1"
            'Runs code
         Case "group5btn1"
            'Runs code
         Case "group6btn1"
            'Runs code
         Case "group7btn1"
            'Runs code
         Case "group8btn1"
            'Runs code
         Case "ToggleReset"
            Call RefreshRibbon(Tag:="*Main")
      End Select
    End Sub