Finding Ribbon Images

Now that Excel 2003 is almost completely out of my life, it’s time to get my many add-ins ribbonized. Here’s what my UIHelpers ribbon looks like.

I used the Custom UI Editor and it was horrible. Did they put the VBE team on that project? I think I’ll find an alternative for the next add-in I convert. I don’t mind XML so much. The absolute worst part of creating a ribbon is finding a suitable button image. I downloaded Jim Rech’s add-in from Ron’s site. I scrolled through some button pages, but with 3,500 images, that wasn’t going to work.

Eventually, I changed the IsAddin property so I could see the list of image names. Then I filtered the names based on some keywords. Once I had a good candidate, I’d go back up to the ribbon, find that button, and look at it. This was much better than browsing through all of the pages hoping I’d find something suitable.

As you can imagine, I couldn’t leave well enough alone. I modified Jim’s code so I could filter the images based on their names directly on the ribbon. Jim had a nice system for what he wanted to do and I spent far too much time trying to shoehorn this new feature into that system. After a while, I started, more or less, from scratch. I should have done that from the start.

I started by adding a textbox to the ribbon where the filter term will go. It looks like this:

<editBox id="EditFilter" label="Filter " screentip="Filter on control name" getText="GetCtrlFil" maxLength="20" sizeString="xxxxxxxxxxxxxxxxxxxx" onChange="EditFilterEntry" />

I don’t know what all that means, I just copied Jim’s and changed a few things. For the control handling part, I created two variables: mcolFiltered and mcolShown. mcolFiltered is a collection that holds all of the controls that match the filter. If there’s no filter, it simply holds all of the controls. When the ribbon loads, it sets up some module-level variables.

Private Sub FilterImagesRibbonLoaded(ribbon As IRibbonUI)
    Set mRib = ribbon
    mlStart = 1
    mlSize = eButtonSize.Normal
    msWhat = vbNullString
End Sub

mlStart determines which member of the collection to show first. ResetListToUse gets the button names from a spreadsheet. msWhat is the filter term – set to nothing to start.

Private Sub SetButtons()
    Dim i As Long
    Set mcolShown = New Collection
    Set mcolFiltered = New Collection
    For i = LBound(mvaButtons, 1) To UBound(mvaButtons, 1)
        If InStr(1, mvaButtons(i, 1), msWhat, vbTextCompare) Then
            mcolFiltered.Add mvaButtons(i, 1), mvaButtons(i, 1)
        End If
    Next i
    If mlStart + ButtonsShown > mcolFiltered.Count Then
        mlStart = mcolFiltered.Count - ButtonsShown + 1
    End If
    If mlStart < 1 Then
        mlStart = 1
    End If
    For i = mlStart To mcolFiltered.Count
        mcolShown.Add mcolFiltered(i), mcolFiltered(i)
        If mcolShown.Count >= ButtonsShown Then Exit For
    Next i
End Sub

SetButtons handles what’s shown. First mcolFiltered is populated with all the control names that match the filter. Then mlStart is validated to make sure it’s within the range. Lastly, mcolShown is populated with which portion of mcolFiltered is on display. Most of the rest of the code just sets one or more module-level variable and calls SetButtons. Here’s some more code, just for fun.

Private Function ButtonsShown() As Long
    If mlSize = eButtonSize.Normal Then
        ButtonsShown = eButtonShow.Normal
        ButtonsShown = eButtonShow.Large
    End If
End Function

Private Sub EditboxEntry(control As IRibbonControl, text As String)
    Dim lNum As Long
    lNum = CLng(Val(text))
    If lNum <= 0 Then
        mlStart = 1
    ElseIf lNum >= mcolFiltered.Count - ButtonsShown + 1 Then
        mlStart = mcolFiltered.Count - ButtonsShown + 1
        mlStart = lNum
    End If

End Sub

Private Sub SizeCBHandler(control As IRibbonControl, ByRef returnedVal)
    If returnedVal Then 'Large checkbox checked
        mlSize = eButtonSize.Large
        mlSize = eButtonSize.Normal
    End If
End Sub

Private Sub GetNextGroup(control As IRibbonControl)
    If ShiftDown Then
        mlStart = mcolFiltered.Count - ButtonsShown
        mlStart = mlStart + ButtonsShown
    End If

End Sub

Here’s the ribbon showing all of the controls with “filter” in their name.

As verbose as the image names are, they don’t contain enough information to do a proper search. Searching for “filter” works well enough, but if you want something related to money, you won’t find one search term that gets the job done. We need some meta data around each of the images. The first image is of a zero and is named “_0”. That image needs to turn up for searches such as zero, nil, number, digit, telephone, and probably some others. With 3,500 images, I’m not too interested in filling out all of that meta data. We need to crowd source it. Or hire some poor people.

Come to think of it, all those captchas that you have to type to prove you’re human are a lot of wasted effort. I should make a captcha system that shows a picture and asks the user to type two words that come to mind. I won’t actually check the words against anything, but I’ll use them to build my meta database for these images. Sure the captcha won’t work, but by the time people figure that out, I’ll already have my data. Brilliant.

You can download


  1. Martin says:

    I did this while ago

    it containts form that displays all the imageMSOs and they can be filtered out.

  2. Jeff Weir says:

    I’ve recently spent hours and hours trolling through these. Real pain. Sometimes you find one and think ‘Maybe…if I can’t find anything better’, and keep scrolling without noting anything down. Once you inevitably DON’T find anything better, then scrolling through all those images again looking for the ‘Maybe’ one is like searching for a needle in a haystack filled with needles. I swear that one ‘Maybe’ was removed by gremlims, causing me to scroll through the whole lot many times before said gremlins put it back in again.

    Ha – captcha idea is funny. I think you’d get an over-representation of ‘WTF’ though.

    Aside: It’s about time that MS refreshed some of the more low-res images to higher-res.

  3. Dick Kusleika says:!124&authkey=!AGI-PeGdEe7pAIo

    I just added meta data to the first 100 items. Brutal. Only 3,400 more to go.

  4. Dick Kusleika says:

    That’s nice Martin. I can’t figure out why our counts are different on the same filter. Also, it seems like if I choose large or small I get different results. I like it in a userform though.

  5. MSimms says:

    Guys – I’ve been thru this crazy image searching experience.
    it’s not that hard to make your own custom images and show them in the ribbon.
    Of course, you must get Steven Bullens most excellent graphic library so you can use the PNG file format.
    I purchased an icon editor, and used an image from it in the Ribbon.
    Then I made my own in Photoshop in the PNG format.
    Incredibly, the PNG image was clearer and more precise than the one created by the icon editor !

  6. Doug Glancy says:

    I’ve ribbonized a couple of addins that other people use. It’s tedious, so for most addins I’m happy enough using old Excel 2003 menu-building code. I add a “Menu Commands” button to the Quick Access toolbar and just get to my addins from there. I actually kind of like having them all on one button. (I also use my MenuRighter tool to add my utility addin to several right-click menus).

  7. Guys, Awesome job! Anybody know how Jim Rech retrieved the image names from the ImageMso0-1 in the word doc’s backstage?

  8. Kevin DeWhitt says:

    I have used Andy Pope’s Visual Ribbon Editor a couple of times and like it very much. You might give that a spin…

  9. Ron de Bruin says:

    Hi Dick

    Ken have also a add-in on his site

    This link will be also on my new site that I upload in two weeks
    Will also check out your code then

    Have a nice day

Posting code or formulas in your comment? Use [cc] tags!

  • [cc_vb]Block of code goes here[/cc_vb]
  • [cci_vb]Inline code goes here[/cci_vb]
  • [cc]Formula goes here[/cc]

Leave a Reply