> ## Content Index
> Fetch the complete content index at: https://nolongerset.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Returning Values By Reference in Ribbon Callbacks
- URL: https://nolongerset.com/byref-ribbon-callbacks/
- Published: 2023-03-18T02:05:58.000Z
- Updated: 2026-05-08T12:51:01.000Z
- Description: To return a value from a ribbon callback, you need to pass the value back to the calling procedure using an argument that has been passed by reference.
- Author: Mike Wolfe
- Tags: Subs vs. Functions, Ribbon, #Import 2026-05-20 02:59

This article is one in a [series on Subs vs. Functions](https://nolongerset.com/subs-vs-functions/) in VBA.

---

One of the "additional facts" from my Subs vs. Functions article was this:

> Sometimes you MUST use a `Sub`, *even if you *do need* its return value* (e.g., ribbon callbacks).

This is something of a corollary to the fact that [sometimes you MUST use a Function, even if you **don't need** its return value](https://nolongerset.com/functions-called-from-property-sheet/).

## Ribbon Callbacks

An Office [ribbon callback](https://nolongerset.com/ribbon-callbacks/) is a VBA subroutine that gets triggered in response to various ribbon events. 

Some events occur automatically, such as when the ribbon initially loads. Other events occur in response to user actions, such as clicking on a button. Some callbacks can be forced to run by using the [Invalidate method](https://learn.microsoft.com/en-us/office/vba/api/Office.IRibbonUI.Invalidate), which forces reevaluation of every callback in the ribbon, or the [InvalidateControl method](https://learn.microsoft.com/en-us/office/vba/api/office.iribbonui.invalidatecontrol), which is restricted to a single control.

Some [ribbon callbacks](https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/aa722523%28v=office.12%29#how-can-i-determine-the-correct-signatures-for-each-callback-procedure), such as those associated with the **getVisible** and **getEnabled** ribbon properties, must return information to the Ribbon UI. Others, such as those set in the **onAction** and **onChange** properties, are simply raised by the ribbon but do not return information to the ribbon.

## "Returning" Values to a Ribbon Callback

For technical reasons having to do with [COM](https://nolongerset.com/what-the-heck-is-com/), you cannot use a Function to return a value to the ribbon.

To return a value from a ribbon callback, you need to pass the value back to the calling procedure using an argument that has been [passed by reference](https://nolongerset.com/one-if-by-val-two-if-by-ref/). When you pass an argument by reference, you pass a reference to the memory location of the variable, rather than a copy of the variable itself. This means that any changes made to the variable within the called Sub are reflected in the calling procedure.

For example, consider a ribbon button defined with the following XML:

```xml
<button id="MyCustomButton" label="My Custom Button" size="large"
        onAction="MyButton_Click" getEnabled="MyButtonEnabled" />
```

When the ribbon first loads, the `MyButtonEnabled()` Sub will be called. Here's what that sub might look like:

```vba
Sub MyButtonEnabled(Control As IRibbonControl, ByRef Enabled)
    Enabled = UserIsAdmin()
End Sub
```

In this example, the `MyButtonEnabled()` Sub is the ribbon callback for the **getEnabled** property of a ribbon command button. The `Control` argument represents the control that triggered the callback.

The `ByRef Enabled` argument is used to pass the return value of the `UserIsAdmin()` function back to the calling procedure. The `UserIsAdmin()` function is a custom function that determines whether the current user is an administrator.

If the `UserIsAdmin()` function returns `True`, the `Enabled` argument is set to `True`, and the button is enabled. If the function returns `False`, the `Enabled` argument is set to `False`, and the button is disabled.

By using a ribbon callback for the **getEnabled** property and passing the return value of the `UserIsAdmin()` function back to the calling procedure, we can ensure that the button is only shown to users who have administrative privileges.

### Referenced articles

[Subs vs. Functions in VBAWhat is the difference between a Sub and a Function and why would you use one or the other? I’ll give you the short answer...and then we can explore the long answer.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/02/Designer--3-.png)](https://nolongerset.com/subs-vs-functions/)

[One if ByRef, and Two if ByValArguments in VBA are passed by reference by default. What does that mean? And what are the differences between passing by reference and by value?![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2020/09/lantern-1864627_1920.jpg)](https://nolongerset.com/one-if-by-val-two-if-by-ref/)

*Cover image created with [Microsoft Designer](https://designer.microsoft.com/)*

##### Acknowledgements

- Portions of this article's body generated with the help of [ChatGPT](https://nolongerset.com/chatgpt-nls/)
- One or more code samples generated with the help of [ChatGPT](https://nolongerset.com/chatgpt-nls/)