动态显示/隐藏自定义功能区选项卡

问题描述 投票:0回答:1

目前我正在开发一个自定义功能区选项卡(使用 Office CustomUI 编辑器),当用户导航到名称中包含“Roster”的任何页面时显示/隐藏该选项卡。下面是我的 XML:

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="RibbonOnLoad">
<ribbon>
    <tabs>
      <tab id="customRosterTab" label="Roster Tools" getEnabled="IsRosterTabEnabled">
        <group id="rosterGroup" label="Roster Actions" />
      </tab>
    </tabs>
  </ribbon>
</customUI>

我在 ThisWorkbook 模块中使用 VB 脚本:

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Not ribbonUI Is Nothing Then
        ribbonUI.Invalidate ("customRosterTab") ' Forces the ribbon to refresh, calling IsRosterTabEnabled
    End If
End Sub

以及下面的脚本位于单独的模块中:

Dim ribbonUI As IRibbonUI

' Initialize ribbon UI
Sub RibbonOnLoad(ribbon As IRibbonUI)
    Set ribbonUI = ribbon
    MsgBox "Ribbon has loaded successfully!"
End Sub

' Callback function to enable/disable the tab based on sheet name
Function IsRosterTabEnabled(control As IRibbonControl) As Boolean
    ' Enable tab if the active sheet's name contains "Roster"
    IsRosterTabEnabled = InStr(1, ActiveSheet.Name, "Roster", vbTextCompare) > 0
End Function

不幸的是,每次我更改为名称中包含“Roster”的任何工作表时,我都会在“If NotribbonUIIsNothingThen”这一行上收到“ObjectRequired”错误(因为ribbonUI为空)。

我不知道如何解决这个问题。有人可以提供任何见解吗?

excel vba xml custom-ui
1个回答
0
投票

有两个原因可以解释您收到的错误:

  1. 正如第一条评论中所述,对象声明是错误的,无法从
    ThisWorkbook
    代码模块访问它。因此,它必须声明为:
  Public ribbonUI As IRibbonUI
  1. 遇到 VBA 错误时,保存在变量中的功能区对象可能会丢失。对于这种情况,您应该保存/记住它的内存指针。请复制保留特定功能区子项的标准模块中的下一个代码:
Option Explicit

'This goes in the standard module top part, in the declarations area:
'To memorize the Ribbon object pointer! _____________________________________
#If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As LongPtr)
#Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
#End If
'______________________________________________________________________

Public ribbonUI As IRibbonUI
Const strRib As String = "\MyRibb"

' Modify the initialization of ribbon UI in the next way:
Sub RibbonOnLoad(ribbon As IRibbonUI)
    Dim Path As String: Path = Environ("temp") & strRib
    Dim File As Integer: File = FreeFile
    Open Path For Output As #File
        Print #File, ObjPtr(ribbon) 'memorize IRibbonUI pointer
    Close #File

    Set ribbonUI = ribbon
    Debug.Print "Ribbon has loaded successfully!"    
End Sub

Sub getRibbon() 'reSet ribbonUI if it was lost (it's Nothing):
    Dim Path As String: Path = Environ("temp") & strRib
    Dim File As Integer: File = FreeFile
    Dim ribValue As String
    
    If ribbonUI Is Nothing Then
        Open Path For Input As #File
            Input #File, ribValue
        Close #File
        
        #If VBA7 Then
            CopyMemory ribbonUI, CLngPtr(ribValue), 8 'place in memory IRibbonUI object from its memorized pointer '64 bit
        #Else
            CopyMemory ribbonUI, CLng(ribValue), 4    'place in memory IRibbonUI object from its memorized pointer
        #End If
        Debug.Print "Ribbon object recuperated..."
    End If
End Sub

在上述模块中保留所有必要的功能,您已经使用的子功能。

现在,按以下方式修改您的事件代码:

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If ribbonUI Is Nothing Then getRibbon 'ribbon object is recuperated if lost

    ribbonUI.Invalidate ("customRosterTab") ' Forces the ribbon to refresh, calling IsRosterTabEnabled
End Sub
© www.soinside.com 2019 - 2024. All rights reserved.