ENFR
See the add-ins
Practical guide

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.

Updated on 17 September 2026 · 15 min read · Excel on Windows

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 :

customUI14.xml
<?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.

Why customUI14 and not customUI

There 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:

  1. Close the workbook and make a backup copy of it.
  2. Rename MonClasseur.xlsm to MonClasseur.zip.
  3. Open the archive and create at its root a folder called customUI containing your customUI14.xml.
  4. Edit _rels/.rels and 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.

Never unzip the whole workbook

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.

Module1 — VBA
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.

The ribbon variable gets lost

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:

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:

  1. The relationship is missing in _rels/.rels. The XML is there, Excel is not looking at it.
  2. An id duplicated, or a misspelt attribute. The XML is strict, and case matters: onAction, not onaction.
  3. The workbook was saved as .xlsx. The customUI survives, but the macros behind the buttons do not.
  4. The file is blocked by Windows because it came from an e-mail or a download: right-click → Properties → Unblock.
  5. 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 delivered

Frequently 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.

Read next

Guide Create your folders from Excel The macro to put behind your first button. Development A ribbon designed for your trade See what can be wired behind a button: APIs, Python, checks, deliverables.