Adding your own buttons to the Excel ribbon
A macro launched through Alt + F8 and a list of names is only ever used by whoever wrote it. The same macro behind a button, in a tab bearing your name, becomes a tool the whole team uses without thinking about it.
Three methods, only one serious
Customising the ribbon through Excel's options (File → Options → Customize Ribbon) creates a tab… on your machine, for all your workbooks. The colleague who opens the file sees nothing. Useful for yourself, useless for distributing a tool.
The Quick Access Toolbar can be attached to one particular workbook. But it only offers small icons in a row, with no groups and no labels: beyond three buttons, nobody knows which does what.
The customUI file is the only route that gives a real tab, travels with the workbook and appears identically on every machine. It is what every professional Excel add-in does. It calls for writing a little XML — thirty lines or so that you will never touch again.
The customUI file, explained
Here is a complete tab, with two groups and three buttons. Save it under the name
customUI14.xml, in UTF-8 :
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon>
<tabs>
<tab id="ongletMaison" label="My tools" insertAfterMso="TabHome">
<group id="grpDossiers" label="Dossiers">
<button id="btnCreer"
label="Create the folder"
size="large"
imageMso="FolderNew"
onAction="RubanCreerDossier"
screentip="Creates the tree for the active row"/>
<button id="btnOuvrir"
label="Open"
size="large"
imageMso="FileOpen"
onAction="RubanOuvrirDossier"/>
</group>
<group id="grpDocs" label="Documents">
<button id="btnDevis"
label="Generate the quote"
size="large"
imageMso="FileCreateDocumentWorkspace"
onAction="RubanGenererDevis"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Four attributes are worth pausing on.
idmust be unique in the whole file. One duplicate identifier, and the entire tab disappears with no message.insertAfterMso="TabHome"places your tab just after “Home”. Without that attribute, it lands last, far to the right, where nobody looks for it.size="large"gives a tall button with the icon above the text.size="normal"produces a small line: keep it for secondary actions.screentipis the tooltip. On a shared tool, it is what heads off the question “what does this button do?”.
customUI14 and not
customUIThere are two namespaces: the 2006 one, for Excel 2007, and the 2009 one used here, which brings contextual tabs and drop-down menus. The file must be named customUI14.xml and sit in a folder called
customUI. To target Excel 2007 as well, you have to supply both files.
Putting it inside the workbook
An .xlsm file is a ZIP archive. All you have to do is drop the XML into it and declare its presence. The comfortable way goes through
Office RibbonX Editor, free and open source: open the workbook, insert an “Office 2010 Custom UI Part”, paste the XML, save. Nothing else to do.
The manual way, worth understanding because it is what explains the breakdowns:
- Close the workbook and make a backup copy of it.
- Rename
MonClasseur.xlsmtoMonClasseur.zip. - Open the archive and create at its root a folder called
customUIcontaining yourcustomUI14.xml. - Edit
_rels/.relsand add this line just before</Relationships>:
<Relationship Id="rIdCustomUI"
Type="http://schemas.microsoft.com/office/2007/relationships/ui/extensibility"
Target="customUI/customUI14.xml"/>
Then rename the archive back to .xlsm and reopen it. Without that relationship, the XML is present in the file but Excel never reads it: it is the most frequent cause of a tab that does not appear.
Extracting the complete archive and then re-zipping it produces a file Excel refuses to open: the order of the entries and the compression mode of the first file both matter. Work in the archive, by drag and drop, or use a tool that preserves its structure.
Wiring the buttons to your macros
The onAction attribute names the VBA procedure called on click. That procedure has a signature imposed on it: it receives one argument, the control that triggered it.
Option Explicit
' The signature is imposed by the ribbon: one IRibbonControl argument.
' Without it, the click triggers nothing, and no error message appears.
Public Sub RubanCreerDossier(control As IRibbonControl)
CreerLesDossiers ' your usual macro
End Sub
Public Sub RubanOuvrirDossier(control As IRibbonControl)
Dim chemin As String
chemin = ActiveSheet.Cells(ActiveCell.Row, 3).Value
If Len(Dir(chemin, vbDirectory)) > 0 Then
Shell "explorer.exe """ & chemin & """", vbNormalFocus
Else
MsgBox "No folder for this row.", vbInformation
End If
End Sub
The IRibbonControl type only exists if the workbook contains a customUI. If the VBA editor says “User-defined type not defined”, it is because the XML was not loaded: go back over the relationship step.
Enabling or greying out a button according to context
An “Open the folder” button only makes sense on a row that has one. The ribbon can handle that, at the cost of a little plumbing: a variable that keeps hold of the ribbon, and a callback that answers the question “is this button active?”.
Public gRuban As IRibbonUI
' Called once, when the workbook loads.
Public Sub RubanCharge(ribbon As IRibbonUI)
Set gRuban = ribbon
End Sub
' Called by Excel to find out whether the button should be enabled.
Public Sub BoutonActif(control As IRibbonControl, ByRef retour)
retour = (Len(ActiveSheet.Cells(ActiveCell.Row, 3).Value) > 0)
End Sub
On the XML side, add onLoad="RubanCharge" to the
<customUI> and getEnabled="BoutonActif"
element on the button. Excel only queries this callback at the moments it judges useful: to force a re-evaluation after the selection changes, call
gRuban.Invalidate from the
Worksheet_SelectionChange.
Any uncaught VBA error resets the global variables:
gRuban becomes Nothing, and
Invalidate raises error 91 — the user then sees a frozen ribbon. The remedy is to store the ribbon pointer in a hidden cell and rebuild it when needed. That is the kind of detail that separates a demonstration from a tool that holds up in production.
Icons: 7,000 available free
The imageMso reuses Office's own icons. They are already on every machine, they adapt to the light or dark theme and to high-density screens. A few useful values:
FolderNew,FileOpen,FileSaveAs— files and foldersTableInsert,RefreshAll,FilterClearAll— dataFileCreateDocumentWorkspace,EnvelopesAndLabelsDialog— documents and mailHappyFace,FlagRed,TagsTaskPane— statuses and markers
To see the complete list, Office RibbonX Editor offers a visual picker, and Microsoft publishes the full galleries as a download. An unknown icon causes no error : the button simply shows with no image — check the spelling, case matters.
For your own logo, you have to go through image="monLogo", declare loadImage on the customUI and supply the image from VBA. That is more work, and the result often degrades on very dense screens: Office's icons remain the best effort-to-result ratio.
When the tab does not appear
Excel says nothing by default when it rejects a customisation. Start by turning the messages on : File → Options → Advanced → General → “Show add-in user interface errors”. Excel will then point you at the offending line.
The causes, in order of frequency:
- The relationship is missing in
_rels/.rels. The XML is there, Excel is not looking at it. - An
idduplicated, or a misspelt attribute. The XML is strict, and case matters:onAction, notonaction. - The workbook was saved as
.xlsx. The customUI survives, but the macros behind the buttons do not. - The file is blocked by Windows because it came from an e-mail or a download: right-click → Properties → Unblock.
- The archive was re-zipped in its entirety, breaking the structure of the Office package.
A tab that appears but whose buttons do nothing comes down to a single cause: the procedure's signature. Check that it really is
Public Sub Nom(control As IRibbonControl), in a
standard module — never in a sheet's module nor in
ThisWorkbook.
And if you would rather not maintain it yourself
When the ribbon has to call your trade software's API, launch your Python scripts, check a sheet or produce your deliverables, writing the XML is no longer the point: it is the business logic that has to go behind the buttons.
See examples of trade ribbons → Free quotation within 48 working hours · from €500 incl. VAT · source code deliveredFrequently asked questions
Do I need Office RibbonX Editor to create a ribbon?
No: everything can be done by editing the workbook's ZIP archive by hand, as described above. The editor saves time and validates the XML along the way, which avoids most invisible tabs, but it brings nothing the format does not already allow.
Should my tab replace Excel's own tabs?
It would be a bad idea, but it is possible: startFromScratch="true" on the customUI element hides the whole standard ribbon. Users then lose access to saving, formatting and paste special. Keep that mode for completely locked-down applications.
Does the ribbon work in Excel for Mac?
Partly. Excel for Mac reads the customUI and shows the tab, but several attributes are ignored, some imageMso icons do not exist, and getEnabled callbacks behave differently. A ribbon designed for Windows must be retested from end to end on a Mac before being distributed.
How do I distribute my ribbon to the whole team?
Two routes. The .xlsm workbook carries its ribbon with it: everyone opens the file, the tab appears. Or you convert the lot into an .xlam add-in, installed once per machine, and the tab becomes available in every workbook. The first route is simpler, the second more comfortable in use.
Can I add drop-downs, check boxes, a gallery?
Yes: dropDown, comboBox, checkBox, gallery, menu and splitButton all exist in the schema. Each needs its own VBA callbacks (getItemCount, getItemLabel, onChange…), which soon runs to a hundred lines. Start with buttons, and only add a rich control where it saves a real gesture.