如何使用VBA添加自定义功能区选项卡?


98

我正在寻找一种在Excel功能区中添加自定义标签的方法,该标签将带有几个按钮。我碰巧有一些资源可以通过Google解决,但所有这些看起来都很晦涩难懂且异常复杂。

快速简便的方法是什么?我希望在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

请确认您使用的是哪个Excel版本?
Siddharth Rout 2012年

那是专案。
Nathan_Sav '17

Answers:


146

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

我使用称为“ 自定义UI编辑器”的免费实用程序为Excel应用程序/加载项创建选项卡。


编辑:适应OP的新请求

讲解

这是承诺的简短教程:

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

    在此处输入图片说明

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

    在此处输入图片说明

  3. 下一步单击菜单插入| XML示例| 自定义标签。您会注意到基本代码是自动生成的。现在,您都可以按照自己的要求进行编辑。

    在此处输入图片说明

  4. 让我们检查一下代码

    在此处输入图片说明

    label="Custom Tab":将“自定义标签”替换为您要为其指定标签的名称。暂时将其称为“ Jerome”。

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

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

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

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

演示版

这样,让我们​​创建2个按钮,并将其命名为“ JG Button 1”和“ JG Button 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文件另存为启用宏的文件。现在,当您单击“笑脸”或“太阳”时,您将看到相关的消息框:

在此处输入图片说明

希望这可以帮助!


6
是的:)罗恩在他的网站上有很多例子。rondebruin.nl/ribbon.htm
Siddharth Rout

1
您要创建一个新的标签页吗?如果是,那么请提供更多详细信息,我将为您提供XML代码:)
Siddharth Rout 2012年

1
给我20分钟 使用相关代码和快照更新以上文章:)
Siddharth Rout 2012年

6
@SiddharthRout +1-我发现我不需要任何Excel书籍,只需关注您的帖子,就可以满足我在几天的工作中需要学习的知识(今天晚上,它是Ribbon XML!):)
我们的人香蕉

1
我建议您使用基本的xml代码和VBA代码创建一个新的询问,然后在那儿采取它的形式?@YasserKhalil
Siddharth Rout

30

我能够使用Excel 2013中的VBA来完成此任务。不需要特殊的编辑器。您需要的是Visual Basic代码编辑器,可以在“开发人员”选项卡上进行访问。默认情况下,“开发人员”选项卡不可见,因此需要在“文件”>“选项”>“自定义功能区”中启用它。在“开发工具”选项卡上,单击“ Visual Basic”按钮。代码编辑器将启动。右键单击左侧的“项目资源管理器”窗格。单击插入菜单,然后选择模块。将以下两个子项添加到新模块中。

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中的LoadCustRibbon子项打开甚至打开,并调用ThisWorkbook代码文件的Before_Close事件中的ClearCustRibbon子项。


这对我有用,但仅遇到一些小问题。1)如果我保留Before_Close事件,则不会加载新功能区。2)当我设法通过删除Before_Close事件使功能区工作时,我不得不重新加载Excel,然后它才会出现。如果您能告知为什么会这样,那太好了!
Petay87

代码完全一样吗?你可以张贴吗?想法是Excel应该在加载功能区之前修改标准功能区文件,并在关闭工作簿之前对其进行重置。必须重置功能区,因此它不会显示在其他工作簿中。
Roi-Kyi Bryant

3
此代码将覆盖用户可能已经进行的所有当前功能区自定义。
WizzleWuzzle '18

@WizzleWuzzle不必。功能区可以导入并解析为可以遍历的对象。然后可以将新元素添加到对象。结果可以保存到文件中。问题是如何创建自定义功能区。而不是如何修改现有的。
黎伊·布莱恩特

1
@ Roi-Kyi-Bryant问题是要添加一个自定义功能区项目,而不是覆盖整个当前的自定义功能区。此代码将覆盖当前功能区。
WizzleWuzzle '18

24

我疯狂地挣扎,但这实际上是正确的答案。对于它的价值,我想念的是:

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

顺便说一下,罗恩网站上解释它的页面现在在 http://www.rondebruin.nl/win/s2/win002.htm

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

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


2
我仍然认为(5年后)最佳答案,也许OP @BuZz想刷新原始帖子,至少指向此答案(?)。我几乎找不到它,因为它位于相当长的答案列表的底部。
Chri.s

18

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

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

要使按钮与您的自定义宏配合使用,请按照此SO回答- 从功能区调用excel宏中的说明,在 .xlam子对象中设置要调用的宏。基本上,您需要将“ Control As IRibbonControl”参数添加到功能区xml指向的任何模块中。另外,您的功能区xml应该具有onAction =“ myaddin!mymodule.mysub”语法,以正确调用该加载项加载的任何模块。

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


1
对于那些没有所有开发工具的人来说,这是可行的。感谢您的“简单”解决方案
Evan 2015年

2
我曾经教过第二年的编程学生这种方法,但最终发现,如果可以访问CustomUI工具,它的使用就简单了许多。
瑞克·亨德森

8

除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

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


您将如何以此传递参数?我一直在使用它,但是找不到传递参数的方法。
jDave1984 '16

使用我的答案,您将在每个子例程中添加一个参数列表,例如LoadCustomRibbon(tabName作为String,groupName作为String,btnName作为String)。然后按照@Erikas指出的那样在适当的位置调用这些子例程。
黎伊·布莱恩特

6

多个插件试图修改功能区时,我在Roi-Kyi Bryant的解决方案中遇到了困难。我的工作计算机上也没有管理员权限,因此无法安装Custom UI Editor。因此,如果您与我同在一条船上,那么这是一个仅使用Excel自定义功能区的替代示例。请注意,我的解决方案来自Microsoft指南


  1. 创建要自定义功能区的一个或多个Excel文件。就我而言,我已经创建了两个.xlam文件,Chart Tools.xlam并且Priveleged 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文件名后缀a 。就我而言,我改名Chart Tools.xlamChart Tools.xlam.zip,并Privelged UDFs.xlamPriveleged UDFs.xlam.zip
  2. 打开每个.zip文件,然后导航到该_rels文件夹。将.rels文件复制到_rels您在步骤3中创建的文件夹中。使用文本编辑器编辑每个 .rels文件。从Microsoft指南

在final <Relationship>元素和close <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. .zip从您创建的Excel文件中删除文件扩展名
  4. 如果已创建.xlam文件,请返回Excel,将其添加到Excel加载项。
  5. 如果适用,请在每个外接程序中创建回调。在第4步中,onAction我的按钮中包含关键字。该onAction关键字指示,含元素被触发时,Excel应用程序将触发子例程后直接封装在引号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. 如果您希望加载项共享Ribbon元素,请使用idQand xlmns:关键字。在我的示例中,Chart Tools.xlamPriveleged UDFs.xlam都可以访问具有idQ等于x:chartToolsTab和的元素x:privelgedUDFsTab。为此,x:必须这样做,并且我已经在customUI.xml文件的第一行中定义了其命名空间<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" xmlns:x="sao">Microsoft指南中的两种自定义Fluent UI的方法一节提供了更多详细信息。
  2. 如果您希望加载项访问Excel附带的Ribbon功能区,请使用isMSO关键字。Microsoft指南中的两种自定义Fluent UI的方法一节提供了更多详细信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.