隐藏单个自定义功能区按钮

时间:2013-08-04 13:11:50

标签: vba excel-vba ribbon excel

我有一个自定义excel功能区和一个excel外接程序,其中包含一个在打开工作簿时实例化一次的类。根据类的某些属性,我需要隐藏自定义功能区中的某些按钮(所有按钮都在同一个选项卡中)。

我的自定义功能区是:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="loadCustom">
<ribbon>
<tabs>
<tab id="tab1" label="customTab" getVisible="GetVisible" tag="myTab">
<group id="grp1" label="Group1" imageMso="ViewFullScreenView" getVisible="GetVisible">
    <button id="Bt1" size="large" label="Button1" imageMso="AccessListIssues" onAction="runBt1" visible="true"/>
    <button id="Bt2" size="large" label="Button2" imageMso="AccessListTasks" onAction="runBt2" visible="true"/>
    <button id="Bt3" size="large" label="Button3" imageMso="ControlLayoutStacked" onAction="runBt3" visible="true"/>
    <button id="Bt4" size="large" label="Button4" imageMso="ControlLayoutTabular" onAction="runBt4" visible="true"/>

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

然后,我在模块中使用以下VBA宏来加载自定义功能区和/或禁用它:

Public Sub loadCustom(ribbon As IRibbonUI)

    Set RibUI = ribbon

    If workbookTitle = "myWorkbook" Then
        MyTag = "show"
    Else
        MyTag = False
        RefreshRibbon MyTag
    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 RefreshRibbon(Tag As String)
    MyTag = Tag
    If RibUI Is Nothing Then
        MsgBox "Error, Save/Restart your workbook"
    Else
        RibUI.Invalidate
    End If
End Sub

在我的特定工作簿中,功能区应该加载我有一个隐藏的工作表,我的类模块类从中读取每个按钮的值以确定它是否应该显示。一旦我读到这个值,我怎么能隐藏一个单独的按钮?我发现的所有示例似乎只适用于标签。我可以将ribbonUI传递给类并循环遍历每个控件吗?我一直无法找到这样做的方法。谢谢你的帮助!

2 个答案:

答案 0 :(得分:5)

您需要在运行时自定义功能区。

检查我的问题(并回答)here虽然我的问题出现在PPT VBA中,但我在Excel中进行了测试,问题的解决方案应该非常相似。

不是将boolean truefalse分配给每个按钮的visible属性,而是需要另一个回调,以便在加载此选项卡时,该过程检查您的类对象已经实例化,然后根据需要设置truefalse

例如,在我的PPT中,我的XML部分就像:

...
<tab idMso="TabView">
               <group idMso="GroupMasterViews" getVisible="VisibleGroup"/>
               <group idMso="GroupPresentationViews" getVisible="VisibleGroup"/>
           </tab>
           ...

因此,我使用自定义属性Visible来调用宏getVisible,而不是使用该组的VisibleGroup属性。我遇到了一些细微差别,例如,我无法在不同的类型控件上使用相同的回调/宏,因此为什么我有两个回调(EnabledControl和{{1两者都做完全相同的事情。我不知道为什么,不幸的是,这部分开发似乎没有很好的记录。

检查我的代码,看看我在测试时放置断点的所有地方。我不得不做很多调试才能让它工作。在每个过程中放置​​断点并逐步执行代码。这是一个痛苦的屁股,但如果你已经走到这一步,我相信你将能够使它工作。

更新

我对PPT加载项进行了简短的测试。在功能上这是类似的,所以我测试比尝试在Excel中重新创建所有内容更容易。

我的加载项有自己的菜单组和一些自定义按钮。相关的按钮行是这样的:

VisibleGroup

完整的XML供您参考:

<button id="HelpButton" label="Help" getVisible="EnableControl" onAction="HelpFile" />

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customUI onLoad="RibbonOnLoad" xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <commands> <command idMso="ViewSlideSorterView" getEnabled="EnableControl"/> <command idMso="ViewNotesPageView" getEnabled="EnableControl"/> <command idMso="ViewSlideShowReadingView" getEnabled="EnableControl"/> <command idMso="ViewSlideMasterView" getEnabled="EnableControl"/> <command idMso="ViewHandoutMasterView" getEnabled="EnableControl"/> <command idMso="ViewNotesMasterView" getEnabled="EnableControl"/> <command idMso="WindowNew" getEnabled="EnableControl"/> </commands> <ribbon startFromScratch="false"> <tabs> <tab idMso="TabView"> <group idMso="GroupMasterViews" getVisible="VisibleGroup"/> <group idMso="GroupPresentationViews" getVisible="VisibleGroup"/> </tab> <tab id="TabTiger" label="Chart Builder" insertAfterMso="TabDeveloper"> <group id="GroupTigerMain" label="XXXX Chart Builder"> <menu id="TigerMenu" image="XXXXLogo" size="large"> <button id="LaunchButton" label="Launch Chart Builder" onAction="ShowChart_Form" /> <button id="InfoButton" label="Info" onAction="Credit_Inf" /> <button id="VersionButton" label="Version" onAction="VersionNum" /> <button id="HelpButton" label="Help" getVisible="EnableControl" onAction="HelpFile" /> </menu> </group> </tab> </tabs> </ribbon> </customUI> 例程看起来像这样(我故意取消注释EnableControl以便我可以打破并输入代码,你可能想要这样做只是为了调试并确保正确的布尔值被传递给控件):

MsgBox

您需要修改指定Sub EnableControl(control As IRibbonControl, ByRef returnedVal) returnedVal = Not TrapFlag 'TrapFlag = True indicates the Application is running. MsgBox ("GetEnabled for " & control.Id) 'Debug.Print control.Id & " enabled = " & CStr(returnedVal) Call RefreshRibbon(control.Id) End Sub 的逻辑以满足您的目的。但基本上这个宏应该每次触发按钮即将显示,所以在我的情况下,每当我打开包含它的菜单时它就会触发。

只要在returnedVal之前returnedVal的值为False,则该过程有效,并且我的菜单栏中的按钮不再可见。

答案 1 :(得分:0)

在Excel中我注意到,只有当此工作簿可见时(窗口打开未最小化),才会显示嵌入WB的功能区。 我玩过各种可见和可见的选项,但是如果包含它的工作簿的窗口被最小化,我就无法保持功能区。 解决方法是使用包含功能区的.xlam Addin。然后,无论您在Excel中打开的工作簿的状态如何,都会显示功能区。