More Outlook Resource Sites

Microsoft Developer Network (MSDN)

FAQs and other general resources

share code 18-Dec-2018 14:18

Looking for help with Outlook programming projects — VSTO, add-ins, VBA, custom Outlook forms, etc.? You′ve come to the right place!

NEW! >> Subscribe to this site via RSS. For more RSS options, see the complete list of feeds on our main news page.

Code level: advanced    Code area: Outlook Expert Techniques Printer Friendly Version
Title: Dynamic menu items
Description: Demonstrates how to dynamically add menu items.
Date: 06-Jul-2007  15:58
Code level: advanced
Code area: Outlook Expert Techniques
Posted by: Steve Bateman
This message is displayed as VB.NET
 Paste the code as directed below, then right-click any outlook menu and choose customise. Add a menu called "TestMenu", then run the "Test_buttons" macro. Delete the TestMenu menubar after.

---------- Paste code into Module called "DynamicMenus" ----------
Option Explicit

Private myButtons As Collection

Public Sub AddButtonHandler(aButton As CommandBarControl, Optional reInit As Boolean = False)
  Dim myMenuItem As DynamicMenuItem
  Dim i As Integer
  If reInit Or myButtons Is Nothing Then Set myButtons = New Collection
  Set myMenuItem = New DynamicMenuItem
  Set myMenuItem.aControl = aButton
  myButtons.Add myMenuItem
End Sub

Public Sub DynamicMenuClicked(ByVal Ctrl As CommandBarControl)
  Call MsgBox(Ctrl.Tag, vbOKOnly, Ctrl.Caption)
End Sub

Public Sub Test_buttons()

  Dim anExplorer As Explorer
  Dim anInspector As Inspector
  Dim aCommandBar As CommandBar
  Dim aControl As CommandBarControl
  Dim currItemClass As OlObjectClass
  Dim i As Integer

  For Each anExplorer In Application.Explorers
    For Each aCommandBar In anExplorer.CommandBars
      If aCommandBar.Name = "TestMenu" Then
        For i = aCommandBar.Controls.Count To 1 Step -1
          aCommandBar.Controls(i).Delete
        Next
        ' Add a button
        Set aControl = aCommandBar.Controls.Add(Type:=msoControlButton)
        With aControl
          .Caption = "Item 1"
          .Tag = "... returns whatever is in item 1's tag"
        End With
        Call AddButtonHandler(aControl, True)
        ' Add a button
        Set aControl = aCommandBar.Controls.Add(Type:=msoControlButton)
        With aControl
          .Caption = "Item 2"
          .Tag = "... has something else in its tag"
        End With
        Call AddButtonHandler(aControl)
        ' Add a button
        Set aControl = aCommandBar.Controls.Add(Type:=msoControlButton)
        With aControl
          .Caption = "Item 3"
          .Tag = "... is not like the others"
        End With
        Call AddButtonHandler(aControl)
      End If
    Next aCommandBar
  Next anExplorer

End Sub
-------- Paste code into a Class called "DynamicMenuItem" --------
Option Explicit

Dim WithEvents myButton As CommandBarButton
Dim myControl As CommandBarControl

Property Set aControl(anyControl As CommandBarControl)
  If anyControl.Type = msoControlButton Then
    Set myButton = anyControl
  Else
    Set myControl = anyControl
  End If
End Property

Property Get aControl() As CommandBarControl
  If Not myButton Is Nothing Then
    aControl = myButton
  Else
    aControl = myControl
  End If
End Property

' "on button click" processing
Private Sub myButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
  Call DynamicMenuClicked(Ctrl)
End Sub
All 11comments
Page [ 1 2 Next >>  
  07-Jul-2007  04:17   
Thought I'd add some comments to explain the example ...

The example shows how to add menu items "on the fly", and have the menu click for all these menu items come back to a single macro. For anyone reading this, the question is probably "why would you want to do this, when it's already possible to add a menu item and associate it with a macro?".

I'm working on some macros to file messages I receive into my folders, keeping track of the last 10...20...100 folders used and bringing the most recent to the top of the heap each time. Kind of a "most recently used filefolder". I have it working with 10 items, but to do this I created 10 subs - each one calls a generic "file the item" sub with a 0-9 parameter specifying which MRU folder to file in. Having use this for a bit, I'm finding I have some folders that I file to all the time, and some others that seem to change day to day, week to week. The more repidly changing folders are in a different mailbox (added to my profile), so I thought to present the MRU folder list as a two-level menu, with mailbox/PST as the top level, and MRU folders as the second level. As a folder was used, it would move to the top of the folder list for the mailbox/PST and would move the mailbox/PST to the top of the first-level menu. Complicated? Could be ...

The problem was how to go about achieving the two-level menu system *without* creating 100 subs that all call a generic sub. With the technique above, I can now create as many menu items as needed, set each one's tag property to be the folder to file in, and route the 'click' from all of them to a single sub that uses the menuitem tag to do the filing ...

I'm sharing the technique so that others with similar needs (multiple menus that all do essentially the same thing - like MRU lists) can use it.

It also demonstrates, using a module and a class, how to capture and use menu click events - which is another question frequently asked.

Anyway, hope you find it useful.
  20-Nov-2007  04:59   
Im using Outlook 2003 at the office.
Somewhere it just will not add menu items.

I made a macro to forward emails and move them to sub folders(pst) and to save their attachments if they contain specific files.

To add 10 to 30 knobs on each computer in the company is't do able, besides its niftier when the menu's can be created based on a network placed file.

Is their any code Im missing or am I doing anything wrong? I took your code as is and only renamed the root name after the first try didn't work.
  20-Nov-2007  05:52   
Hi - for the Test_buttons() routine to work you need to add an empty menu bar called "TestMenu", then run the macro. You should end up with three buttons on the menu bar, and when you click them each should display a message box with the customer tag.

Note that the code is only to demonstrate how to create menu items "on the fly" that trigger vb code when clicked, passing whatever was stored in the .tag property for the menu item. The code *does not* implement all the stuff necessary to record folders used for filing, and to file new items into the remembered folders ...
  20-Nov-2007  09:00   
Uhm yup,
doesn't work here.
I don't get any error codes nor does he adds three menu Items.

I also tried different ways to add menus but it seems that my outlook doesn't accept it.
  20-Nov-2007  12:30   
K. To check what's happening I would "step into" the macro, then step through using F8 to see which line of code is not working. At least for the test_buttons() routine, this should be possible to do.

BTW - this code is working for me on OL2003 - which version do you have?
  22-Nov-2007  09:55   
in the aCommandbar.name i see the names lika advanced and clipboard passing by but not the name TestMenu. So he skips the entire code of set aControl and with aControl.

Whe are working with OL2003 SP2.

Edit:
Made an mistake with adding a menu and menu item.
  22-Nov-2007  09:55   
It works now!
  22-Nov-2007  11:35   
Hmm only one thing left.
Now that it works Im making the code bigger.

Open "C:\buttons.inf" For Input As #1
  
  For Each anExplorer In Application.Explorers
    For Each aCommandBar In anExplorer.CommandBars
      If aCommandBar.Name = "TestMenu" Then
        For i = aCommandBar.Controls.Count To 1 Step -1
          aCommandBar.Controls(i).Delete
        Next
        ' Add a button
            Do Until EOF(1)
                Input #1, Str1, Str2
                    Set aControl = aCommandBar.Controls.Add(Type:=msoControlButton)
                    With aControl
                        .Caption = Str1
                        .Tag = Str2
                    End With
                Call AddButtonHandler(aControl, True)
            Loop
      End If
    Next aCommandBar
  Next anExplorer

Close #1

The last button the code adds works, the first few gets added but the Tag info behind it doesn't work any more.

Im debugging my code after the weekend, got some other things to do besides being a coorparate slave ;) lol

If anyone sees the problem please let me know.
  22-Nov-2007  12:49   
Hi - remove the 'True' from the call to AddButtonHandler. Including this parm re-initializes the collection holding the items that trigger when a button is pressed.

To be clear, you need to replace 'Call AddButtonHandler(aControl, True)' with 'Call AddButtonHandler(aControl)'.
  26-Nov-2007  08:18   
Ok tnx :)
Works like a charm.
Page [ 1 2 Next >>