Create a Category Toolbar in Outlook 2007


I met Nathan Elson for the first time yesterday when I responded to one of his tweets. In his tweet Nathan asked if some twitterverse resident knew of a way to modify Outlook and “create a toolbar button that assigns a category”. He explained that he would rather add or remove categories from his emails by clicking a single toolbar button rather than having to click Outlook’s Categories button and select from the resulting pull down menu. Two clicks versus one unless of course the category Nathan wants doesn’t appear on the pull down list. When that happens he’ll have to click All Categories from the pull down menu and then choose a category from the Color Categories dialog-box. That drives the click count to three and introduces the possibility of scrolling the list in order to find the category he’s looking for. While I might debate the logic of building a new toolbar to save a single click the toolbar could actually save two clicks and possibly prevent the need to scroll too. The discussion wouldn’t be complete without mentioning that Nathan could eliminate all clicks and the need for a toolbar by assigning a shortcut key to each category. Of course he’d have to remember the shortcut key and Outlook allows a limited set of shortcut keys, enough for just 11 categories. If he has more than that, then he’s out of luck.

Fortunately for Nathan it’s very simple to add a toolbar to Outlook. Toolbars can be added manually or via a script. In Nathan’s case the solution is to use a script. Why a script? There are a couple of reasons. First, Outlook doesn’t have a built-in toolbar button for adding/removing categories. It does offer the same Categories toolbar button that appears on Outlook’s built-in menu which is exactly what Nathan wants to move away from. Second, even if it were possible to add a toolbar button for a specific category, then Nathan would have to edit the toolbar each time he adds/removes a category since toolbars do not have an autoupdate capability. The ideal solution is one that would detect when categories have been added/deleted and update the toolbar on its own. Unfortunately that’s not possible because Outlook’s Categories object has no events. A script can’t react to a change if the change isn’t detectable. The script is still a better solution though because Nathan won’t have to add/remove buttons manually. All he’ll have to do is restart Outlook.

At less than 100 lines of code the script for this is surprisingly simple when you consider what it has to do. The script starts by building the toolbar. To do that it creates a toolbar, populates it with a button for each of Nathan’s categories, then displays the toolbar on screen. When Nathan clicks one of the buttons on the toolbar the script checks to see if the category associated with that button is already assigned to the currently selected item. If that category is not assigned to the item, then it adds it. If instead it finds that the category is already assigned, then it removes it. In other words the button is a toggle. The script works with all Outlook item types.

Before I present the code there are a couple of caveats I need to mention.

  1. This solution only works with Outlook 2007. It will not work with any other version of Outlook. Outlook 2003 and earlier used a completely different approach to categories and is therefore incompatible. Outlook 2010 uses the same categories system as Outlook 2007 but it has eliminated toolbars in favor of the ribbon system used by the other Microsoft Office products. The ribbon is inaccessible by scripts.
  2. The toolbar buttons this script creates are not color coded to match the color of the category each button is associated with. Toolbar buttons support a picture, a caption, or both. They do not support simply coloring the button.

On to the script. It comes in three parts. The first two are class modules, one to implement the toolbar and the other to implement the buttons that go on the toolbar. The third bit of code gets the process started by creating an instance of the toolbar class each Outlook is launched and destroying it each time Outlook closes.

Toolbar Button Class.

Private WithEvents objButton As Office.CommandBarButton
Private strThisCat As String

Private Sub Class_Terminate()
    Set objButton = Nothing
End Sub

Private Sub objButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
    Dim olkItm As Object, arrCats As Variant, varCat As Variant, bolFound As Boolean, intCnt As Integer, strNewCat As String
    Select Case TypeName(Outlook.Application.ActiveWindow)
        Case "Explorer"
            Set olkItm = Outlook.Application.ActiveExplorer.Selection(1)
        Case "Inspector"
            Set olkItm = Outlook.Application.ActiveInspector.CurrentItem
    End Select
    arrCats = Split(olkItm.Categories, ", ")
    For Each varCat In arrCats
        If varCat = strThisCat Then
            bolFound = True
        Else
            strNewCat = strNewCat & ", " & varCat
        End If
    Next
    If Not bolFound Then
        strNewCat = strNewCat & ", " & strThisCat
    End If
    olkItm.Categories = strNewCat
    olkItm.Save
    Set olkItm = Nothing
End Sub

Public Sub Init(ByRef ofcParentBar As Office.CommandBar, ByVal strCatNum As String, strTipText As String)
    Set objButton = ofcParentBar.Controls.Add(msoControlButton)
    With objButton
        .Caption = strCatNum
        .Style = msoButtonCaption
        .TooltipText = strTipText
    End With
    strThisCat = strTipText
End Sub

Instructions. Follow these instructions to add the code to Outlook.

  1. Start Outlook
  2. Click Tools > Macro > Visual Basic Editor
  3. If not already expanded, expand Microsoft Office Outlook Objects
  4. Right-click on Class Modules, select Insert > Class Module
  5. In the Properties panel click on Name and enter CatBtn
  6. Copy the code and paste it into the right-hand pane of Outlook’s VB Editor window
  7. Click the diskette icon on the toolbar to save the changes
  8. Close the VB Editor

Toolbar Class.

'--- On the next line change True to False if you do not want the categories sorted ---'
Private Const SORT_CATS = True
Enum intSortType
    dicSortKey = 1
    dicSortItem = 2
End Enum

Private ofcBar As Office.CommandBar
Private colBtns As Collection

Private Sub Class_Initialize()
    Set colBtns = New Collection
    CreateCATBar Outlook.Application.ActiveExplorer
End Sub

Private Sub Class_Terminate()
    Set colBtns = Nothing
    Set ofcBar = Nothing
End Sub

Private Sub CreateCATBar(olkWindow As Object)
    Dim objCatBtn As CatBtn, olkCat As Outlook.Category, objDict As Object, intCnt As Integer, arrKeys As Variant, varKey As Variant
    On Error Resume Next
    Set ofcBar = Outlook.Application.ActiveExplorer.CommandBars("CAT")
    On Error GoTo 0
    If TypeName(ofcBar) = "Nothing" Then
        'Create the toolbar
        Set ofcBar = olkWindow.CommandBars.Add("CAT", msoBarTop, False, True)
    
        'Create the buttons
        Set ofcButton = ofcBar.Controls.Add(msoControlButton)
        With ofcButton
            .Caption = "CAT"
            .Enabled = False
            .Style = msoButtonCaption
        End With
        
        'Create the category buttons
        Set objDict = CreateObject("Scripting.Dictionary")
        For Each olkCat In Outlook.Application.Session.Categories
            objDict.Add olkCat.Name, olkCat.Name
        Next
        If SORT_CATS Then
            Set objDict = SortDictionary(objDict, dicSortKey)
        End If
        arrKeys = objDict.keys
        intCnt = 1
        For Each varKey In arrKeys
            Set olkCat = Outlook.Application.Session.Categories.Item(varKey)
            Set objCatBtn = New CatBtn
            objCatBtn.Init ofcBar, intCnt, olkCat.Name
            colBtns.Add objCatBtn
            Set olkCat = Nothing
            intCnt = intCnt + 1
        Next
        
        ofcBar.Visible = True
    End If
End Sub

Private Function SortDictionary(ByVal objDict, ByVal intSort As intSortType) As Object
'--- This function is from the Microsoft KB article: http://support.microsoft.com/kb/246067 ---'

  ' declare constants
  Const dictKey = 1
  Const dictItem = 2

  ' declare our variables
  Dim strDict()
  Dim objKey
  Dim strKey, strItem
  Dim x, y, z

  ' get the dictionary count
  z = objDict.count

  ' we need more than one item to warrant sorting
  If z > 1 Then
    ' create an array to store dictionary information
    ReDim strDict(z, 2)
    x = 0
    ' populate the string array
    For Each objKey In objDict
        strDict(x, dictKey) = CStr(objKey)
        strDict(x, dictItem) = CStr(objDict(objKey))
        x = x + 1
    Next

    ' perform a a shell sort of the string array
    For x = 0 To (z - 2)
      For y = x To (z - 1)
        If StrComp(strDict(x, intSort), strDict(y, intSort), vbTextCompare) > 0 Then
            strKey = strDict(x, dictKey)
            strItem = strDict(x, dictItem)
            strDict(x, dictKey) = strDict(y, dictKey)
            strDict(x, dictItem) = strDict(y, dictItem)
            strDict(y, dictKey) = strKey
            strDict(y, dictItem) = strItem
        End If
      Next
    Next

    ' erase the contents of the dictionary object
    objDict.RemoveAll

    ' repopulate the dictionary with the sorted information
    For x = 0 To (z - 1)
      objDict.Add strDict(x, dictKey), strDict(x, dictItem)
    Next

  End If

  Set SortDictionary = objDict
End Function

Instructions. Follow these instructions to add the code to Outlook.

  1. Start Outlook
  2. Click Tools > Macro > Visual Basic Editor
  3. If not already expanded, expand Microsoft Office Outlook Objects
  4. Right-click on Class Modules, select Insert> Class Module
  5. In the Properties panel click on Name and enter CatBar
  6. Copy the code and paste it into the right-hand pane of Outlook’s VB Editor window
  7. Click the diskette icon on the toolbar to save the changes
  8. Close the VB Editor

Startup/Shutdown Code.

Dim objCatBar As CatBar

Private Sub Application_Quit()
    Set objCatBar = Nothing
End Sub

Private Sub Application_Startup()
    Set objCatBar = New CatBar
End Sub

Instructions.

  1. Start Outlook
  2. Click Tools > Macro > Visual Basic Editor
  3. If not already expanded, expand Microsoft Office Outlook Objects and click on ThisOutlookSession
  4. Copy the code and paste it into the right-hand pane of Outlook’s VB Editor window
  5. Click the diskette icon on the toolbar to save the changes
  6. Close the VB Editor
  7. Click Tools > Trust Center
  8. Click Macro Security
  9. Set Macro Security to “Warnings for all macros
  10. Click OK
  11. Close Outlook
  12. Start Outlook. Outlook will display a dialog-box warning that ThisOutlookSession contains macros and asking if you want to allow them to run. Say yes.

Putting it All Together.
Once Nathan has added this code and restarted Outlook he should see a new toolbar that looks something like this.

Screenshot of categories toolbar

Categories Toolbar

Is I noted earlier, toolbar buttons can have a picture, a caption, or both. I’ve used the caption in this solution. The caption on each button is a number representing the button’s position on the toolbar. When Nathan moves the mouse pointer over a button the category associated with that button will appear as a tool tip.

Screenshot of the categories toolbar with tooltip showing

Categories Toolbar with Tooltip Showing

When Nathan wants to add/remove a category to/from an item all he as to do is select the item and click the toolbar button for the desired category.

Enhancements.
Here are two enhancements Nathan may want to consider.

  1. Colored icons. Nathan could make a set of icons matching Outlook’s category colors. He could then change the button style (line 36 of the Toolbar Button Class code) to use an icon instead of a caption.
  2. Show Item Categories. Perhaps Nathan would like to see the categories already applied to the currently selected item. To do that he’d have to write code that is triggered each time he selects an item. That code would check the item’s categories and depress the corresponding toolbar button(s).

It’s time to send Nathan a link to this post. I hope he finds the code useful. Here’s hoping that you do too.

Advertisements

44 comments on “Create a Category Toolbar in Outlook 2007

  1. Pingback: gtd – the elson way | Nathan R. Elson

  2. David,
    Will this be possible to do in Outlook 2010 as well. Is the code the same.
    Second question, with regards to subsets of categories, if i name the categories with a prefix like 0-, 1- for the different subsets, can I also make a category button toolbar for each subcategory with a filter in the script to only include categories with the specific prefix.
    Regards Dag

    • Dag,

      No, it won’t be possible to use that code in Outlook 2010 and later versions. Microsoft eliminated toolbars in favor of the ribbon beginning with Outlook 2010. Implementing something like this would now require an add-in, a custom form, or a form region, all of which are more complicated and cannot be done with a script alone.

      Yes, you could make multiple category toolbars by prefixing the category names with some sort of code.

    • David,

      I found a solution utilizing NEOplus. It allows for easy add categories and have very good functionality.
      Thank you for your time.

      Dag
      ASA Slickline Sales Manager
      Located in Jakarta
      � HP: +62 811 191729
      •: dhenriksen@slb.com

      “It is amazing what you can accomplish if you do not care who gets the credit.”
      Harry S. Truman

  3. Hi David, I’m new to your blog (fascinating by the way) and found this by a categories google search. Apologies if replies such a long time after the last one are welcome or if this is not on topic enough. I don’t know if I am odd in my use of categories but I’ve been using them for 10 to 15? years (for categorizing emails) and was horrified at the clumsy Outlook 2007 implementation I saw after our recent upgrade.
    I find it way quicker to type in a few categories than to select from a list, especially as I probably have hundreds that I have used. I think of them as similar to the way the brain works – they have different ‘strengths’ based on how often you use them. Yes I may type the same category differently sometimes but if that happens they generally appear next to each other in emails grouped by category so I can just correct the category then if I need to. And like the brain I might forget a category and have to find the email by search, but then I remember it.
    Sorry about the rant, tell me if it is not appropriate, now to the tech. point.
    I added a region to the standard Outlook message from and put a textbox populated with the categories field in it. Now in an open email I can immediately type in all the categories I want to give to the email – Bliss!
    The limit is that I have to open the email to do it. I’d like to have the same textbox on a toolbar so I can do it for the selected email(s). Is that possible?
    Regards
    Dave Easey

    • Hi, Dave.

      No worries on the rant.

      That might be possible. What version of Outlook are you using?

  4. Pingback: Quora

  5. Hi David,

    Thanks for the tip: this should do what I need. However, I got a compilation error I cannot solve by myself…

    “Ambiguous name detected: Application_Quit”

    Same problem with “Application_Startup”

    If I rename these functions, the toolbar doesn’t show up.

    Any help welcome!
    Vince

    • Hi, Vince.

      The compilation error is saying that procedures named Application_Startup and Application_Quit already exist. You need to combine them into a single Application_Startup and Application_Quit.

    • Yep, of course… Woke up too early! Now it works fine, thanks!

      Another question: Is it possible to replace the button names (1, 2, 3, etc) by the actual category names? I don’t mind about the colors, but names are really key. Can we also limit the buttons to a sublist of categories?

      Many thx in advance.
      Vince

    • Yes, both are possible. I used numbers instead of category names for two reasons. In comparison to a number a category name is long which means uneven button sizes and fewer buttons. The latter is a serious issue for anyone who has a moderately long list of categories. Limiting the buttons to a sublist of categories will either require that the category names follow a pattern or you’ll have to actually put the names in the code. The former is more preferable, but either one will work.

  6. David, thanks for sharing your expertise. I had to make the quote and ambersand replacement but it worked like a charm. Might inspire me to learn how to add the icon code.

    • Hi there, nice peace of code, however I question. How the clicking on buttons is implemented? I never found a .OnClick property of button used and it also does not work for me. Anything I overlooked?

      Thanks a lot,
      otherwise very usefull feature, wanted to make my own like this.

      Rado

    • Hi, Rado.

      Thanks, I’m glad you like it. The action performed when a button is clicked is implemented in the Toolbar Button Class. The click is handled by the objButton_Click subroutine.

      I’m not clear on what you mean when you say “… it also does not work from me.” Do you mean the code isn’t working at all? If so, then what version of Outlook are you using and do you have macros enabled?

  7. Would really like to get this working, and your effort is much appreciated. First, I got an undefined variable error (Set ofcButton =)because my editor is set to Option Explicit. I disabled that and got another compile error “Method or data member not found” at objCatBtn.Init in CatBtn. That’s as far as I’m going to get without your help. Am I missing a reference?

    • Hi, Dave.

      Open the VB editor in Outlook and add a reference to “Microsoft Office 12.0 Object Library”. If you aren’t on Office 2007 (which is 12.0), then use the version number for your version (e.g. for Office 2010 it’ll be 14.0). Try the code again once you’ve added the reference.

  8. Excellent work. Much needed toolbar and clear, readable code.
    If you could get icons on those it would be absolutely perfect. I’m going to play with this myself to see if I can get that done.
    Anyway this is great.

    • Thanks, Matan! Icons are possible. I didn’t use them for a couple of reasons. First, they’d make each button bigger, so you’d wouldn’t be able to get as many of them on a toolbar. That’s fine if you have a small number of categories, but it’d be a problem if you have a lot of categories. Second, you’re pretty limited in your selection of images to go on the buttons. Outlook’s built-in mechanism for button faces uses a small, predefined set. You can expand on that by switching to a larger predefined set, but there’s no built-in mechanism for adding your own. There might be ways to overcome that, but, frankly, I’ve never explored that to see what’s possible.

  9. Hello David
    You gave me some invaluable help earlier this year in sorting the Category toolbar.
    Of course now I have an additional question.
    The Categories menu option lists the most recent 15 categories used.
    Is it possible to create a toolbar which just shows those 15?
    Many thanks
    Steve

  10. I love this functionality but it doesn’t work for me either. I get a syntax error when I try to apply a category to an item. The lines below that I’ve marked with *** are RED in the debugger.

    Private Sub objButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
    Dim olkItm As Object, arrCats As Variant, varCat As Variant, bolFound As Boolean, intCnt As Integer, strNewCat As String
    Select Case TypeName(Outlook.Application.ActiveWindow)
    *** Case “Explorer”
    Set olkItm = Outlook.Application.ActiveExplorer.Selection(1)
    *** Case “Inspector”
    Set olkItm = Outlook.Application.ActiveInspector.CurrentItem
    End Select
    ***arrCats = Split(olkItm.Categories, “, “)
    For Each varCat In arrCats
    If varCat = strThisCat Then
    bolFound = True
    Else
    ***strNewCat = strNewCat & “, ” & varCat
    End If
    Next
    If Not bolFound Then
    strNewCat = strNewCat & “, ” & strThisCat
    End If
    olkItm.Categories = strNewCat
    olkItm.Save
    Set olkItm = Nothing
    End Sub

    • Interesting. When I pasted the lines into this post they display without the jumble. When I copy them and paste them back into outlook the first two lines now work. There are still errors however with these two:

      strNewCat = strNewCat & “, ” & varCat

      strNewCat = strNewCat & “, ” & strThisCat

  11. Mr. Lee…
    I have tried to start this script but it does not seem to work….
    I wish I could send you a screen shot of what I am looking at…
    Under modules i see nothing..
    Only under class modules I have Class 1, 2 and 3….
    Wish I knew what I was doing wrong….
    This script is very important to me.
    marshall at 73 dot com

    • I’ve sent you an email. Send me a screen shot and I’ll see if I can figure out what’s going wrong.

  12. Great article. Thanks for posting it. This approach to selecting categories is exaclty what I am looking for. The only problem is our company is using 2003… I hope to use it if/when we migrate.

  13. I think so–when I search for two single quotes side by side, I don’t find any. And when I search for the double quotes, I find what looks like double quotes.

    It pasted funny earlier–this is literally what it says
    Case ampersand quot semi-colon Explorer ampersand quot semi-colon

    I put the two exported class files as
    getmike.info\CatBtn.cls and CatBar.cls
    darned if I can see the problem

  14. I’m back to fiddling with this again.
    Now, when I press a button, I get an error at
    Private Sub objButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
    Dim olkItm As Object, arrCats As Variant, varCat As Variant, bolFound As Boolean, intCnt As Integer, strNewCat As String
    Select Case TypeName(Outlook.Application.ActiveWindow)
    Case "Explorer"
    the last line I pasted in gives the error. I can’t see any problem with it vis a vis what’s above

  15. This looks & works great.
    Is there any way in which I can sort the categories alphabetically before they get assigned to buttons?
    Thanks

    • Hi, Steve.

      That’s a great suggestion. I’ve modified the code to give the option of sorting the categories when the bar is created. By default the categories will be sorted. If you don’t want the categories sorted, then change the constant CAT_SORT to False on line #2 of the code for the Toolbar class.

      For anyone who had already installed the code, all you need to do is replace the Toolbar class with the revised version (above).

  16. Pingback: gtd – the elson way « nathan·r·elson

    • Hi, Michael.

      The problem is the “"” scattered throughout the code. Those are supposed to be double-quotes. The copy and paste screwed up. If you fix them all, then you should be in good shape.

    • David,

      The two scripts for the toolbar have the same name and throw up an error for the code. Is there a way we should change the code to make it work?

      Dave

    • Hi, David.

      Looks like you found a typo that I missed. Step #5 of the instructions for the Toolbar class should read CatBar not CatBtn.

      Thanks for pointing that out to me.

      Cheers!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s