GetAttr(): Ribbon XML String-Building Helper Function

When you're building strings in code with lots of optional values--such as ribbon XML attributes--this simple function helps keep your code readable.

GetAttr(): Ribbon XML String-Building Helper Function

I build my custom Access ribbon interfaces by generating the ribbon XML entirely in code and then loading it at startup via Access's LoadCustomUI method.

To keep that approach manageable, I rely on several helper functions to build the XML strings.  The GetAttr() function is a simple function that handles the fact that ribbon XML nodes can have many attributes and most are optional.  

For example, here is a list of available attributes for the button control:

  • description / getDescription
  • enabled / getEnabled
  • id / idMso / idQ
  • image / imageMso / getImage / getImageMso / showImage / getShowImage
  • insertBeforeMso / insertBeforeQ / insertAfterMso / insertAfterQ
  • keytip / getKeytip
  • label / getLabel / showLabel / getShowLabel
  • onAction
  • screentip / getScreentip
  • size / getSize
  • supertip / getSupertip
  • tag
  • visible / getVisible

Keeping Things Readable

Good programmers write computer-readable code.
Great programmers write human-readable code.

In my ribbon XML building class, I have a Button() method with several optional parameters:

Public Sub Button(BtnImage As Variant, BtnCaption As String, _
                  CallbackFunction As String, _
                  Optional BtnSize As RibbonControlSize = RibbonControlSizeRegular, _
                  Optional getEnabledCallback As String = vbNullString, _
                  Optional getVisibleCallback As String = vbNullString, _
                  Optional IsToggleButton As Boolean = False, _
                  Optional KeyTip As String = vbNullString, _
                  Optional ScreenTip As String = vbNullString, _
                  Optional SuperTip As String = vbNullString)
    '--== {unrelated code omitted for clarity} ==--
    Const Delim As String = " "
    Dim Attrs As String
    Attrs = Conc(Attrs, GetAttr("getEnabled", getEnabledCallback), Delim)
    Attrs = Conc(Attrs, GetAttr("getVisible", getVisibleCallback), Delim)
    Attrs = Conc(Attrs, GetAttr("keytip", KeyTip), Delim)
    Attrs = Conc(Attrs, GetAttr("screentip", ScreenTip), Delim)
    Attrs = Conc(Attrs, GetAttr("supertip", SuperTip), Delim)
    Debug.Print Attrs
    '--== {unrelated code omitted for clarity} ==--

End Sub

Here's an example of how I might call this method (this is an excerpt from my standard report print preview ribbon):

Ribbon.Button "ExportExcel", "Excel", "rbExportToExcel", _
              RibbonControlSizeRegular, _
              KeyTip:="E", _
              ScreenTip:="Export to Excel file", _
              SuperTip:="(Requires Microsoft Excel)"

And here is the value of the Attrs variable that gets output to the immediate window:

keytip="E" screentip="Export to Excel file" supertip="(Requires Microsoft Excel)"

What's most noteable about the above string is what's NOT there.  The getEnabled and getVisible attributes are both missing from the above string, even though there were calls to both GetAttr("getEnabled", ...) and GetAttr("getVisible", ...) in the Button method.  That's because the getEnabledCallback and getVisibleCallback variables were both set to their default vbNullString values.

The GetAttr() function simply returns a null string if the attribute value passed to it is a zero-length string.

The Code

There's not much to see within the code for the GetAttr() function itself.  The real power is in how it combines with the Conc() function to help generate highly-readable calling code as demonstrated above.

' Procedure : GetAttr
' Author    : Mike Wolfe
' Source    :
' Date      : 10/8/2015
' Purpose   : Returns an attribute name=value pair if AttrVal is a non-zero-length string
'               otherwise returns a null string.
Function GetAttr(AttrName As String, AttrVal As String) As String
    If Len(AttrName) = 0 Then Throw "Missing attribute name"
    If Len(AttrVal) > 0 Then GetAttr = AttrName & "=" & Qt(AttrVal)
End Function


You'll need my Throw() routine if you want to leave the guard clause in place as the first line of the function.  You can always remove that line if you want, but I try to err on the side of programming defensively.

Image by Alfred Derks from Pixabay

All original code samples by Mike Wolfe are licensed under CC BY 4.0