109

我正在寻找一种在 Excel 功能区中添加自定义选项卡的方法,该选项卡将带有几个按钮。我偶然发现了一些通过谷歌解决它的资源,但所有资源看起来都很狡猾而且非常复杂。

有什么快速简单的方法来做到这一点?我希望在我的 VBA 加载到 Excel 时加载新选项卡。

更新:我从这里尝试了这个示例,但在最后一条指令中出现“需要对象”错误:

Public Sub AddHighlightRibbon()
Dim ribbonXml As String

ribbonXml = "<mso:customUI xmlns:mso=""http://schemas.microsoft.com/office/2009/07/customui"">"
ribbonXml = ribbonXml + "  <mso:ribbon>"
ribbonXml = ribbonXml + "    <mso:qat/>"
ribbonXml = ribbonXml + "    <mso:tabs>"
ribbonXml = ribbonXml + "      <mso:tab id=""highlightTab"" label=""Highlight"" insertBeforeQ=""mso:TabFormat"">"
ribbonXml = ribbonXml + "        <mso:group id=""testGroup"" label=""Test"" autoScale=""true"">"
ribbonXml = ribbonXml + "          <mso:button id=""highlightManualTasks"" label=""Toggle Manual Task Color"" "
ribbonXml = ribbonXml + "imageMso=""DiagramTargetInsertClassic"" onAction=""ToggleManualTasksColor""/>"
ribbonXml = ribbonXml + "        </mso:group>"
ribbonXml = ribbonXml + "      </mso:tab>"
ribbonXml = ribbonXml + "    </mso:tabs>"
ribbonXml = ribbonXml + "  </mso:ribbon>"
ribbonXml = ribbonXml + "</mso:customUI>"

ActiveProject.SetCustomUI (ribbonXml)
End Sub
4

8 回答 8

152

AFAIK 您不能使用 VBA Excel 在 Excel 功能区中创建自定义选项卡。但是,您可以使用 VBA 隐藏/显示功能区组件。此外,您上面提到的链接是针对 MS Project 而不是 MS Excel。

我使用这个名为Custom UI Editor的免费实用程序为我的 Excel 应用程序/加载项创建选项卡。


编辑:以适应 OP 的新要求

教程

这是承诺的简短教程:

  1. 安装自定义 UI 编辑器 (CUIE) 后,打开它,然后单击文件 | 打开并选择相关的 Excel 文件。请确保 Excel 文件在通过 CUIE 打开之前已关闭。我以全新的工作表为例。

    在此处输入图像描述

  2. 如下图所示右键单击,然后单击“Office 2007 自定义 UI 部件”。它将插入“customUI.xml”

    在此处输入图像描述

  3. 下一步 点击菜单插入 | 示例 XML | 自定义选项卡。您会注意到基本代码是自动生成的。现在您已准备好根据您的要求对其进行编辑。

    在此处输入图像描述

  4. 让我们检查一下代码

    在此处输入图像描述

    label="Custom Tab":将“自定义选项卡”替换为您要为选项卡指定的名称。暂时让我们称它为“杰罗姆”。

    下面的部分添加了一个自定义按钮。

    <button id="customButton" label="Custom Button" imageMso="HappyFace" size="large" onAction="Callback" />
    

    imageMso:这是将显示在按钮上的图像。“HappyFace”就是你现在看到的。您可以在此处下载更多图像 ID

    onAction="Callback":“回调”是单击按钮时运行的过程的名称。

演示

有了这个,让我们创建 2 个按钮并将它们称为“JG 按钮 1”和“JG 按钮 2”。让我们保持第一个形象的快乐脸,让我们保持第二个“太阳”的形象。修改后的代码现在如下所示:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="MyCustomTab" label="Jerome" insertAfterMso="TabView">
<group id="customGroup1" label="First Tab">
<button id="customButton1" label="JG Button 1" imageMso="HappyFace" size="large" onAction="Callback1" />
<button id="customButton2" label="JG Button 2" imageMso="PictureBrightnessGallery" size="large" onAction="Callback2" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>

删除所有在 CUIE 中生成的代码,然后粘贴上面的代码代替。保存并关闭 CUIE。现在,当您打开 Excel 文件时,它将如下所示:

在此处输入图像描述

现在是代码部分。打开 VBA 编辑器,插入一个模块,然后粘贴以下代码:

Public Sub Callback1(control As IRibbonControl)

    MsgBox "You pressed Happy Face"

End Sub

Public Sub Callback2(control As IRibbonControl)

    MsgBox "You pressed the Sun"

End Sub

将 Excel 文件另存为启用宏的文件。现在,当您单击笑脸或太阳时,您将看到相关的消息框:

在此处输入图像描述

希望这可以帮助!

于 2012-01-13T15:18:25.577 回答
34

我能够在 Excel 2013 中使用 VBA 完成此操作。不需要特殊的编辑器。您所需要的只是 Visual Basic 代码编辑器,它可以在“开发人员”选项卡上访问。Developer 选项卡默认不可见,因此需要在 File>Options>Customize Ribbon 中启用它。在开发人员选项卡上,单击 Visual Basic 按钮。代码编辑器将启动。在左侧的 Project Explorer 窗格中单击鼠标右键。单击插入菜单并选择模块。将下面的两个 subs 添加到新模块中。

Sub LoadCustRibbon()

Dim hFile As Long
Dim path As String, fileName As String, ribbonXML As String, user As String

hFile = FreeFile
user = Environ("Username")
path = "C:\Users\" & user & "\AppData\Local\Microsoft\Office\"
fileName = "Excel.officeUI"

ribbonXML = "<mso:customUI      xmlns:mso='http://schemas.microsoft.com/office/2009/07/customui'>" & vbNewLine
ribbonXML = ribbonXML + "  <mso:ribbon>" & vbNewLine
ribbonXML = ribbonXML + "    <mso:qat/>" & vbNewLine
ribbonXML = ribbonXML + "    <mso:tabs>" & vbNewLine
ribbonXML = ribbonXML + "      <mso:tab id='reportTab' label='Reports' insertBeforeQ='mso:TabFormat'>" & vbNewLine
ribbonXML = ribbonXML + "        <mso:group id='reportGroup' label='Reports' autoScale='true'>" & vbNewLine
ribbonXML = ribbonXML + "          <mso:button id='runReport' label='PTO' "   & vbNewLine
ribbonXML = ribbonXML + "imageMso='AppointmentColor3'      onAction='GenReport'/>" & vbNewLine
ribbonXML = ribbonXML + "        </mso:group>" & vbNewLine
ribbonXML = ribbonXML + "      </mso:tab>" & vbNewLine
ribbonXML = ribbonXML + "    </mso:tabs>" & vbNewLine
ribbonXML = ribbonXML + "  </mso:ribbon>" & vbNewLine
ribbonXML = ribbonXML + "</mso:customUI>"

ribbonXML = Replace(ribbonXML, """", "")

Open path & fileName For Output Access Write As hFile
Print #hFile, ribbonXML
Close hFile

End Sub

Sub ClearCustRibbon()

Dim hFile As Long
Dim path As String, fileName As String, ribbonXML As String, user As String

hFile = FreeFile
user = Environ("Username")
path = "C:\Users\" & user & "\AppData\Local\Microsoft\Office\"
fileName = "Excel.officeUI"

ribbonXML = "<mso:customUI           xmlns:mso=""http://schemas.microsoft.com/office/2009/07/customui"">" & _
"<mso:ribbon></mso:ribbon></mso:customUI>"

Open path & fileName For Output Access Write As hFile
Print #hFile, ribbonXML
Close hFile

End Sub

在 Wookbook open 中调用 LoadCustRibbon sub,在 ThisWorkbook 代码文件的 Before_Close Event 中调用 ClearCustRibbon sub。

于 2015-06-17T13:41:21.093 回答
27

我拼命挣扎,但这实际上是正确的答案。对于它的价值,我错过的是:

  1. 正如其他人所说,无法使用 VBA 创建 CustomUI 功能区,但是,您不需要!
  2. 这个想法是您使用 Excel 的文件 > 选项 > 自定义功能区创建您的 xml 功能区代码,然后将功能区导出到 .customUI 文件(它只是一个 txt 文件,其中包含 xml)
  3. 现在技巧来了:您可以使用他们在此处引用的 MS 工具将 .customUI 代码包含在您的 .xlsm 文件中,方法是从 .customUI 文件中复制代码
  4. 一旦它包含在 .xlsm 文件中,每次打开它时,您定义的功能区都会 添加到用户的功能区中 - 但请务必使用 <ribbon startFromScratch="false" > 否则您会丢失功能区的其余部分。退出工作簿时,功能区将被移除。
  5. 从这里开始很简单,创建您的功能区,从 .customUI 文件复制特定于您的功能区的 xml 代码,并将其放置在如上所示的包装器中(...< tabs> your xml < /tabs.. .)

顺便说一句,在 Ron 的网站上解释它的页面现在位于 http://www.rondebruin.nl/win/s2/win002.htm

这是他关于如何在功能区上启用/禁用按钮的示例 http://www.rondebruin.nl/win/s2/win013.htm

有关功能区的其他 xml 示例,另请参阅 http://msdn.microsoft.com/en-us/library/office/aa338202%28v=office.12%29.aspx

于 2014-03-20T05:40:49.140 回答
19

此处的答案特定于使用自定义 UI 编辑器。我花了一些时间在没有那个精彩程序的情况下创建界面,所以我在这里记录解决方案以帮助其他人决定他们是否需要那个自定义 UI 编辑器。

我遇到了以下微软帮助网页 - https://msdn.microsoft.com/en-us/library/office/ff861787.aspx。这显示了如何手动设置界面,但在指向自定义加载项代码时遇到了一些麻烦。

要使按钮与您的自定义宏一起使用,请在您的 .xlam 子程序中设置要调用的宏,如本 SO 答案中所述 -从功能区调用 excel 宏。基本上,您需要将“控件作为 IRibbonControl”参数添加到从功能区 xml 指向的任何模块。此外,您的功能区 xml 应该具有 onAction="myaddin!mymodule.mysub" 语法以正确调用加载项加载的任何模块。

使用这些说明,我能够创建一个 Excel 插件(.xlam 文件),当我的 VBA 与插件一起加载到 Excel 时,该插件加载了一个自定义选项卡。按钮执行插件中的代码,自定义选项卡卸载时我删除了插件。

于 2015-03-17T03:11:33.967 回答
10

除了 Roi-Kyi Bryant 回答之外,此代码在 Excel 2010 中完全有效。按 ALT + F11 将弹出 VBA 编辑器。双击ThisWorkbook左侧,然后粘贴此代码:

Private Sub Workbook_Activate()

Dim hFile As Long
Dim path As String, fileName As String, ribbonXML As String, user As String

hFile = FreeFile
user = Environ("Username")
path = "C:\Users\" & user & "\AppData\Local\Microsoft\Office\"
fileName = "Excel.officeUI"

ribbonXML = "<mso:customUI      xmlns:mso='http://schemas.microsoft.com/office/2009/07/customui'>" & vbNewLine
ribbonXML = ribbonXML + "  <mso:ribbon>" & vbNewLine
ribbonXML = ribbonXML + "    <mso:qat/>" & vbNewLine
ribbonXML = ribbonXML + "    <mso:tabs>" & vbNewLine
ribbonXML = ribbonXML + "      <mso:tab id='reportTab' label='My Actions' insertBeforeQ='mso:TabFormat'>" & vbNewLine
ribbonXML = ribbonXML + "        <mso:group id='reportGroup' label='Reports' autoScale='true'>" & vbNewLine
ribbonXML = ribbonXML + "          <mso:button id='runReport' label='Trim' " & vbNewLine
ribbonXML = ribbonXML + "imageMso='AppointmentColor3'      onAction='TrimSelection'/>" & vbNewLine
ribbonXML = ribbonXML + "        </mso:group>" & vbNewLine
ribbonXML = ribbonXML + "      </mso:tab>" & vbNewLine
ribbonXML = ribbonXML + "    </mso:tabs>" & vbNewLine
ribbonXML = ribbonXML + "  </mso:ribbon>" & vbNewLine
ribbonXML = ribbonXML + "</mso:customUI>"

ribbonXML = Replace(ribbonXML, """", "")

Open path & fileName For Output Access Write As hFile
Print #hFile, ribbonXML
Close hFile

End Sub

Private Sub Workbook_Deactivate()

Dim hFile As Long
Dim path As String, fileName As String, ribbonXML As String, user As String

hFile = FreeFile
user = Environ("Username")
path = "C:\Users\" & user & "\AppData\Local\Microsoft\Office\"
fileName = "Excel.officeUI"

ribbonXML = "<mso:customUI           xmlns:mso=""http://schemas.microsoft.com/office/2009/07/customui"">" & _
"<mso:ribbon></mso:ribbon></mso:customUI>"

Open path & fileName For Output Access Write As hFile
Print #hFile, ribbonXML
Close hFile

End Sub

不要忘记保存并重新打开工作簿。希望这可以帮助!

于 2016-07-01T06:33:32.703 回答
9

当多个加载项尝试修改功能区时,我在 Roi-Kyi Bryant 的解决方案中遇到了困难。我的工作计算机上也没有管理员访问权限,这排除了安装Custom UI Editor. 因此,如果您和我在同一条船上,这里有一个仅使用 Excel 自定义功能区的替代示例。请注意,我的解决方案源自Microsoft 指南


  1. 创建要自定义其功能区的 Excel 文件/文件。在我的例子中,我创建了两个.xlam文件Chart Tools.xlamPriveleged UDFs.xlam,以演示多个加载项如何与功能区交互。
  2. 为您刚刚创建的每个文件创建一个具有任意文件夹名称的文件夹。
  3. 在您创建的每个文件夹中,添加一个customUI_rels文件夹。
  4. 在每个customUI文件夹中,创建一个customUI.xml文件。该customUI.xml文件详细说明了 Excel 文件如何与功能区交互。Microsoft 指南的第 2 部分customUI.xml介绍了文件中的元素。

我的customUI.xml文件Chart Tools.xlam看起来像这样

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" xmlns:x="sao">
  <ribbon>
    <tabs>
      <tab idQ="x:chartToolsTab" label="Chart Tools">
        <group id="relativeChartMovementGroup" label="Relative Chart Movement" >
            <button id="moveChartWithRelativeLinksButton" label="Copy and Move" imageMso="ResultsPaneStartFindAndReplace" onAction="MoveChartWithRelativeLinksCallBack" visible="true" size="normal"/>
            <button id="moveChartToManySheetsWithRelativeLinksButton" label="Copy and Distribute" imageMso="OutlineDemoteToBodyText" onAction="MoveChartToManySheetsWithRelativeLinksCallBack" visible="true" size="normal"/>
        </group >
        <group id="chartDeletionGroup" label="Chart Deletion">
            <button id="deleteAllChartsInWorkbookSharingAnAddressButton" label="Delete Charts" imageMso="CancelRequest" onAction="DeleteAllChartsInWorkbookSharingAnAddressCallBack" visible="true" size="normal"/>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

我的customUI.xml文件Priveleged UDFs.xlam看起来像这样

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" xmlns:x="sao">
  <ribbon>
    <tabs>
      <tab idQ="x:privelgedUDFsTab" label="Privelged UDFs">
        <group id="privelgedUDFsGroup" label="Toggle" >
            <button id="initialisePrivelegedUDFsButton" label="Activate" imageMso="TagMarkComplete" onAction="InitialisePrivelegedUDFsCallBack" visible="true" size="normal"/>
            <button id="deInitialisePrivelegedUDFsButton" label="De-Activate" imageMso="CancelRequest" onAction="DeInitialisePrivelegedUDFsCallBack" visible="true" size="normal"/>
        </group >
      </tab>
    </tabs>
  </ribbon>
</customUI>
  1. 对于您在步骤 1 中创建的每个.zip文件,为其文件名添加后缀。就我而言,我重命名Chart Tools.xlam为,Chart Tools.xlam.zipPrivelged UDFs.xlamPriveleged UDFs.xlam.zip
  2. 打开每个.zip文件,然后导航到该_rels文件夹​​。.rels将文件复制到_rels您在步骤 3 中创建的文件夹。使用文本编辑器编辑每个文件。 .rels来自微软指南

在最后一个<Relationship>元素和结束 <Relationships>元素之间,添加一行来创建文档文件和自定义文件之间的关系。确保正确指定文件夹和文件名。

<Relationship Type="http://schemas.microsoft.com/office/2006/
  relationships/ui/extensibility" Target="/customUI/customUI.xml" 
  Id="customUIRelID" />

我的.rels文件Chart Tools.xlam看起来像这样

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
        <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
        <Relationship Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" Target="/customUI/customUI.xml" Id="chartToolsCustomUIRel" />
    </Relationships>

我的.rels文件Priveleged UDFs看起来像这样。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
        <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
        <Relationship Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" Target="/customUI/customUI.xml" Id="privelegedUDFsCustomUIRel" />
    </Relationships>
  1. .rels每个.zip文件中的.rels文件替换为您在上一步中修改的文件。
  2. 将您创建的文件夹复制并粘贴到.customUI文件的主目录中.zip
  3. 从您创建的 Excel 文件中删除.zip文件扩展名
  4. 如果您已创建.xlam文件,请返回 Excel 中,将它们添加到您的 Excel 加载项。
  5. 如果适用,请在每个加载项中创建回调。在第 4 步中,我的按钮中有onAction关键字。关键字表示,当触发包含元素时,Excel应用程序将触发紧跟在关键字onAction后面的用引号括起来的子程序。onAction这称为回调。在我的.xlam文件中,我有一个名为的模块CallBacks,其中包含了我的回调子例程。

回调模块

我的CallBacks模块Chart Tools.xlam看起来像

Option Explicit

Public Sub MoveChartWithRelativeLinksCallBack(ByRef control As IRibbonControl)
  MoveChartWithRelativeLinks
End Sub

Public Sub MoveChartToManySheetsWithRelativeLinksCallBack(ByRef control As IRibbonControl)
  MoveChartToManySheetsWithRelativeLinks
End Sub

Public Sub DeleteAllChartsInWorkbookSharingAnAddressCallBack(ByRef control As IRibbonControl)
  DeleteAllChartsInWorkbookSharingAnAddress
End Sub

我的CallBacks模块Priveleged UDFs.xlam看起来像

选项显式

Public Sub InitialisePrivelegedUDFsCallBack(ByRef control As IRibbonControl)
  ThisWorkbook.InitialisePrivelegedUDFs
End Sub

Public Sub DeInitialisePrivelegedUDFsCallBack(ByRef control As IRibbonControl)
  ThisWorkbook.DeInitialisePrivelegedUDFs
End Sub

不同的元素有不同的回调子例程签名。对于按钮,所需的子程序参数是ByRef control As IRibbonControl。如果您不符合所需的回调签名,您将在编译 VBA 项目/项目时收到错误消息。Microsoft 指南的第 3 部分定义了所有回调签名。


这是我完成的示例的样子

完成的产品


一些关闭提示

  1. 如果您希望加载项共享功能区元素,请使用idQandxlmns:关键字。在我的示例中,Chart Tools.xlamandPriveleged UDFs.xlam都可以访问idQ' 等于x:chartToolsTaband的元素x:privelgedUDFsTab。为此,它x:是必需的,并且我在customUI.xml文件的第一行定义了它的命名空间,<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" xmlns:x="sao">. Microsoft 指南中自定义 Fluent UI的两种方法部分提供了更多详细信息。
  2. 如果您希望加载项访问 Excel 附带的功能区元素,请使用isMSO关键字。Microsoft 指南中自定义 Fluent UI的两种方法部分提供了更多详细信息。
于 2019-02-16T02:46:22.507 回答
2

另一种方法是从这个页面下载 Jan Karel Pieterse 的免费 Open XML 类模块:Editing elements in an OpenXML file using VBA

将此添加到您的 VBA 项目后,您可以解压缩 Excel 文件,使用 VBA 修改 XML,然后使用该类重新压缩文件。

于 2020-01-19T22:01:45.930 回答
2

这是一个适用于 Excel 365 的简单解决方案。

首先将此代码输入空白工作簿。

Option Explicit

Sub sbHelloWorld()
 MsgBox "Hello World!"
End Sub

这是基本自定义功能区的 XML。我使用记事本将此 XML 粘贴到名为“rb_HelloWorld.txt”的文件中,然后将其保存并将其复制到文件夹 - “C:\Users\david\AppData\Local\Microsoft\Office” 这个文件夹一开始是隐藏的,所以它需要隐藏。

<mso:customUI      xmlns:mso='http://schemas.microsoft.com/office/2009/07/customui'>
    <mso:ribbon>
        <mso:qat/>
        <mso:tabs>
        <mso:tab idQ="mso:TabDrawInk" visible="false"/>
        <mso:tab id="mso_c1.2A492F1" label="New Tab">
            <mso:group id="mso_c2.2A492F1" label="New Group" autoScale="true">
                <mso:button id="sbHelloWorld" label="sbHelloWorld" imageMso="ListMacros" onAction="sbHelloWorld" visible="true"/>
            </mso:group>
        </mso:tab>
        </mso:tabs>
    </mso:ribbon>
</mso:customUI>

这是用于将新功能区复制到位然后在工作簿退出时将其删除的两个例程。

Sub sbCopyFile()
 Dim sOfficeUIDir As String
 Dim sHWFile As String
 Dim sUIFile As String
 Dim sTest As String
 sOfficeUIDir = "C:\Users\david\AppData\Local\Microsoft\Office\"
 sHWFile = sOfficeUIDir & "rb_HelloWorld.txt"
 sUIFile = sOfficeUIDir & "Excel.officeUI"
 sTest = Dir(sHWFile)
 If Not sTest = "" Then
  FileCopy sHWFile, sUIFile
 End If
End Sub



Sub sbDeleteFile()
 Dim sOfficeUIDir As String
 Dim sUIFile As String
 Dim sTest As String
 sOfficeUIDir = "C:\Users\david\AppData\Local\Microsoft\Office\"
 sUIFile = sOfficeUIDir & "Excel.officeUI"
 sTest = Dir(sUIFile)
 If Not sTest = "" Then
  Kill (sUIFile)
 End If
End Sub

可以使用内置过程 Workbook_Activate 和 Workbook_Deactivate 添加和删除自定义功能区。

Private Sub Workbook_Activate()
 Call sbCopyFile
End Sub

Private Sub Workbook_Deactivate()
 Call sbDeleteFile
End Sub

从自定义功能区上的按钮调用例程 sbHelloWorld()。

于 2021-05-09T18:05:24.157 回答