Ribbon Toolbars

The Excel Ribbon interface can be customized using Jinx. This enables you to add features to Excel in Java or other JVM languages that are properly integrated with Excel for an intuitive user experience.

The ribbon customization is defined using an XML file. This can either be a file referenced by its path, or a resource included in a JAR file. The ribbon is configured by setting either ribbon_xml_file or ribbon_xml_resource in the jinx.ini config file.

The ribbon XML file uses the standard Microsoft CustomUI schema. This is the same schema you would use if you were customizing the ribbon using COM, VBA or VSTO and there are various online resources from Microsoft that document it 1.

Actions referred to in the ribbon XML file are mapped to Java methods using the @ExcelAction annotation.

Creating a Custom Tab

Create a new ribbon xml file. The one below contains a single tab Custom Tab and a single button.

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
    <ribbon>
        <tabs>
            <tab id="customTab" label="Custom Tab">
                <group id="contentGroup" label="Content">
                    <button id="textButton" label="Text Button"/>
                </group>
            </tab>
        </tabs>
    </ribbon>
</customUI>

Set ribbon_xml_file in the config file to the filename of the newly created ribbon XML file. This can be an absolute path, or a path relative to the jinx.ini file.

Note: If ribbon_xml_resource is already set in your jinx.ini file (as it is in the example jinx.ini file) you will need to remove that or comment it out.

[JINX]
ribbon_xml_file = ./ribbon.xml

Alternatively, you can include the ribbon XML file as a resource in a JAR file and use ribbon_xml_resource to tell Jinx where to find the XML file. The example project included with the Jinx download shows how to reference a ribbon XML resource.

Once you’ve configured Jinx start Excel, or reload Jinx if Excel is already started.

Custom Excel ribbon defined in XML

The tab appears in the ribbon with a single text button as specified in the XML file. Clicking on the button doesn’t do anything yet, but in the next section you will see how to assign a button action to a Java method.

Action Methods

Anywhere a callback method is expected in the ribbon XML you can use a Java method annotated with the @ExcelAction annotation. The name used in the ribbon XML should match the name given to the action method via the @ExcelAction annotation.

Many of the controls used in the ribbon have an onAction attribute. This should be set to the name of the registered Java method to be called.

Action methods can be either static or non-static methods. If a non-static method is used the class must have a public constructor that either takes no parameters or a single ExcelAddIn parameter.

package com.xxx.myaddin;

import com.exceljava.jinx.ExcelAction;
import com.exceljava.jinx.IUnknown;

import javax.swing.*;

public class RibbonFunctions {
    @ExcelAction("myaddin.textButtonPressed")
    public static void textButtonPressed(IUnknown control) {
        JOptionPane.showMessageDialog(null,
                "Text button was pressed",
                JOptionPane.INFORMATION_MESSAGE);
    }
}

To add an action handler to the example above first modify the XML file to add the onAction attribute to the text button

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
    <ribbon>
        <tabs>
            <tab id="customTab" label="Custom Tab">
                <group id="contentGroup" label="Content">
                    <button id="textButton"
                            label="Text Button"
                            onAction="myaddin.textButtonPressed"/>
                </group>
            </tab>
        </tabs>
    </ribbon>
</customUI>

The class will also need to be added to the jinx.ini file before reloading Jinx.

[JINX]
classes =
    com.xxx.myaddin.RibbonFunctions
    
[JAVA]
classpath =
    <path to JAR containing RibbonFunctions>

After reloading the ribbon tab will look the same, but now clicking the button will call the textButtonPressed method.

IUnknown Parameters

Many of the ribbon actions take a single control parameter. These are passed from Excel to Java as a COM object, and Jinx exposes these as its own IUnknown type.

The IUnknown type can be converted to a more specific type if you are using a Java COM bridge, such as jinx-com4j.

Jinx will use any registered argument converters to automatically convert from the IUnknown type to the method parameter type. For example, if you are using the jinx-com4j COM bridge you can use the IRibbonControl and IRibbonUI interfaces in your methods instead of IUnknown.

The example from the section above could be written as the following. Note that IUnknown has been replaced with IRibbonControl from the com.exceljava.com4j.office package.

package com.xxx.myaddin;

import com.exceljava.jinx.ExcelAction;
import com.exceljava.jinx.IUnknown;

import com.exceljava.com4j.office.*;

import javax.swing.*;

public class RibbonFunctions {
    @ExcelAction("myaddin.textButtonPressed")
    public static void textButtonPressed(IRibbonControl control) {
        JOptionPane.showMessageDialog(null,
                "Text button was pressed",
                JOptionPane.INFORMATION_MESSAGE);
    }
}

Using Images

Some ribbon controls, like buttons, can use an image to give the ribbon whatever look you like. These controls have an image attribute and a getImage attribute.

The image attribute is set as the argument to an image loader action, which we’ll come to shortly. The getImage attribute is a function that will return a COM object that implements the IPicture interface.

Excel’s default image loader loads images by filename. It’s somewhat limited and doesn’t deal with transparency in PNG image files. Jinx provides another image loader action, jinx.loadImage, that loads an image from a file or resource. It’s recommended to use this instead of the default image loader.

The image loader is set as the loadImage attribute of the customUI element. The following shows a custom ribbon UI with the jinx.loadImage image loader, and a button using a reload.png image.

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
            loadImage="jinx.loadImage">
    <ribbon>
        <tabs>
            <tab id="CustomTab" label="Custom Tab">
                <group id="Tools" label="Tools">
                    <button id="Reload"
                            size="large"
                            label="Reload Jinx"
                            onAction="jinx.reload"
                            image="reload.png"/>
                </group>
            </tab>
        </tabs>
    </ribbon>
</customUI>

If the ribbon XML file is loaded from a file using ribbon_xml_file in the jinx.ini config file, all images are assumed to be filenames relative to the location of the ribbon XML file. If the ribbon XML file is a resource then the images are then also assumed to be resources.

Standard Actions

Jinx contains a handful of standard actions that you can use when building your own ribbon UI.

  • jinx.openLogFile
  • jinx.reload
  • jinx.rebind
  • jinx.about
  • jinx.loadImage

Modifying the Ribbon

Sometimes its convenient to be able to update the ribbon after Excel has started, without having to change the jinx.ini config file.

For example, if your addin is used by multiple users with different roles then one single ribbon may not be applicable for each user. Or, you may want to allow the user to switch between different ribbons depending on what they’re working on.

To manipulate the ribbon programmatically you can use ExcelAddIn.getRibbonXml() and ExcelAddIn.setRibbonXml(java.lang.String).

These can be called as Jinx starts, for example from the constructor of a class that Jinx is loading, to customise how the ribbon is created.

Footnotes