使用自定义功能区关闭并重新打开文档后,Word 会话功能区会发生什么情况?

What happens to the Word session ribbon after closing and reopening a document with a custom ribbon?

我在 Office 365 (Word 11929.20254) 和 Word 2016 上的两个完全不同的 Windows 环境(家庭和工作)中遇到过以下情况,使用了一系列使用 VBA 和 customUI.xml 以显示自定义功能区:

  1. 我打开任何 Word 文档(现有文档或基于 Normal.dotm 的新空白文档)。
  2. 我打开另一个 Word 文档,其中有一个自定义功能区 (customUI.xml);下面的基本示例。
  3. 我用自定义功能区关闭文档。
  4. 我用自定义功能区重新打开文档。
  5. 此时自定义功能区有几处错误(未发生 VBA 错误)。即使第二个文档功能区上的第一个选项卡属于自定义功能区(即它位于“主页”选项卡之前),它也不会激活。 onLoad 回调没有 运行。这只能通过单击自定义功能区选项卡来补救,此时它会弹出(并且 运行s onLoad),或者关闭所有 Word 文档并重新打开。

如果我 运行 在 Excel 或 PowerPoint 中使用与我在上述 Word 中使用的自定义功能区完全相同的自定义功能区的电子表格或演示文稿文件,则第 5 步不适用;功能区正常工作,onLoad 运行s,等等。

为什么 Word 功能区看起来有缺陷,而其他 Office 功能区却没有?开发一个加载项而不是 VBA 和 customUI.xml 会解决或绕过这个问题吗?

编辑:

自定义功能区和关联 VBA 的简单示例如下。将它们放在 Word 文档的 customUI.xml 和 VBA 中,并将其用作第二个 Word 文档,如步骤 2 至 5 中所述。

将功能区和下面的 VBA 放入 Excel 电子表格,然后 运行 通过上面的步骤 1 到 5,除了使用 Excel 电子表格而不是 Word 文档。到达第 5 步时,功能区看起来很好,与 Word 中不同。

customUI.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="modRibbon.CustomUI_OnLoad">
    <ribbon>
        <tabs>
            <tab id="tabCustom" label="Custom" insertBeforeMso="TabHome">
                <group id="grpCustom1" imageMso="EditDocument" label="Custom group 1">
                    <button id="btnA" size="large" label="Aa" imageMso="EditDocument" onAction="modRibbon.btn1A_OnAction" screentip="Aa" supertip="A button."/>
                </group>
                <group id="grpCustom2" imageMso="EditBusinessCard" label="Custom group 2">
                    <button id="btnB" size="large" label="Bb" imageMso="EditBusinessCard" onAction="modRibbon.btn2B_OnAction" screentip="Bb" supertip="Another button."/>
                </group>
            </tab>
        </tabs>
    </ribbon>
</customUI>

modRibbon VBA 模块:

'Callback for customUI.onLoad
Sub CustomUI_OnLoad(ribbon As IRibbonUI)
End Sub

'Callback for btnA_onAction
Sub btn1A_OnAction(control As IRibbonControl)
End Sub

'Callback for btnB_onAction
Sub btn2B_OnAction(control As IRibbonControl)
End Sub

我想出了一个解决方案,到目前为止非常可靠,方法是将以下内容添加到 ThisDocument:

Private Sub Document_Open()

Application.OnTime Now, "modRibbon.ReloadRibbon"

End Sub

并将以下内容添加到 modRibbon VBA 模块(在 OP 中):

Sub ReloadRibbon()

With Application.CommandBars
    .Add "barRibbonRefresher", msoBarTop, False, True 'Adds a dummy bar
    .Item("barRibbonRefresher").Delete 'Deletes the dummy bar above, which appears to force the custom UI, including the custom ribbon, to (re)load
End With

End Sub

这个解决方案:

  • 修复了我在 OP 中概述的问题;因为
  • 它允许用户通过 VBA 随心所欲地重新加载功能区;和
  • 以这种方式重新加载功能区后,回调继续正常工作。

需要注意的是:

  • 修复在 删除 虚拟栏时开始,而不是在添加它时开始;
  • 仅仅将 With 块粘贴到 Document_Open() 中是不够的; OnTime必须使用;
  • OnLoad 回调在功能区重新加载时运行,与打开文档时完全一样。

我认为 CommandBars 有一些特别之处,尤其是 .Delete 方法,它使丝带(恢复)活力,考虑到丝带是应该 replace CommandBars,而不是依赖它们才能使技巧正常运行。

旁注:可能还提供了一种在指针丢失时恢复功能区的更简单方法,这是 VBA 在执行功能区时遇到错误时相当常见的情况方法。 current solution(也适用于 Word)涉及将指针存储在某处(例如在 ThisDocument.Variables 中)然后通过 CopyMemory 恢复它。上述解决方案可能能够简单地重新创建功能区,从而避免任何此类错误。