Adding Menu Items To The VBA Editor 

This page has been replaced. See Creating Menus In The VBA Ediitor.

If you do a lot of VBA coding, you may have wanted to customize the menus in the VBA Editor (VBE).  Unfortunately, this is not as simple as it is with standard Office command bars.  In the VBE, you cannot simply drag around menu items and assign macros.  This is because the VBE is based on the Visual Basic (Visual Studio) model, not the Office model.  Therefore, you have to create and handle your custom menus through code.  

For information about working with menus in Excel, click here.  For general information about programming the VBA Editor, see the Programming To The VBE page.

This page describes the code required to add two simple menu items to the Tools menu of the VBE.  These procedures work for Excel97 and Excel2000.  They will not work in earlier versions of Excel.  Because the VBA procedures here use the CommandBar and CommandBarControl object types, you must set a reference in your VBA Project to the Microsoft Office 8 (or 9) Object Library.

There are two steps in customizing the VBE menus.  First, you have to create new menu items and assign them to a menu and give them captions.  This is the same as you would do to create menu items on the standard Excel menus.  The second step is to associate each item to an instance of a class module that will actually handle the click event for the menu item.   

You'll need a reference to the "Microsoft Visual Basic For Applications Extensibility" module to use the code.  From the Tools menu, choose References, and select this entry from the list. 

First create a class module called VBECmdHandler.   From the Insert menu, choose Class Module.  Select this module in the Project Window, and press F4 to view the Property dialog box.  Change the Name property from Class1 to VBECmdHandler.  

In this class module, enter the following code: 

        


Public WithEvents EvtHandler As VBIDE.CommandBarEvents

Private Sub EvtHandler_Click(ByVal CommandBarControl As Object,_ 
   
  Handled As Boolean, CancelDefault As Boolean)

On Error Resume Next

'
' Run the code specified in the object's OnAction property.
'
Application.Run CommandBarControl.OnAction

'
' Indicate to the Events object that we've successfully handled the event.
'
Handled = True
CancelDefault = True
End Sub

 

 

This is all the code that needs to be in the module.   This code declares an object called EvtHandler  of the type CommandBarEvents.   Since this object is declared with the WithEvents keyword, event triggers are passed to it by the VBE.   This is the object that acts as the "bridge" between your code in this module and the menu items you'll add.   As you'll see later, when you create the menu item, you point the VBE to this object as the "recipient" of the menu click events.  

The EvtHandler_Click event, the only event there is for the EvtHandler object, gets executed when the menu item is clicked.  As you'll see later, we're using one class module with on EvtHandler to manage all of the menu items we're going to add.  Therefore, the code looks at the OnAction property of the CommandBarControl object to determine what procedure to run, which is called with Application.Run.  Unlike standard Excel command bar controls, the OnAction property of controls on VBE command bars does not actually cause the code to be execute.  We use it to store the procedure name which we want to execute, but our code has to manually call that procedure.  

Next, we need to add the code to run create the menu items, and to create the link between the menu item and the class module.  Create a standard code module, and enter in the following global declarations: 

Dim MnuEvt As VBECmdHandler
Dim CmdItem As CommandBarControl
Dim EvtHandlers As New Collection


The
VBECmdHandler  must be the same name as the class module that you created earlier.  This statement creates an object called MnuEvt which is defined by the class VBECmdHandler.   The CmdItem object is a standard CommandBarControl object, and EvtHandlers is a collection where we'll store each  that we create.   Since we're using the same MnuEvt object for each menu item we create, we need to store copies of each instance of that object so that each menu item is handled separately.   

The next step is to create the procedure to add the menu items.  This is shown below.  

Sub AddNewMenuItems()

While EvtHandlers.Count > 0
    EvtHandlers.Remove 1
Wend

With Application.VBE.CommandBars("Menu Bar").Controls("Tools")
    .Reset
    Set CmdItem = .Controls.Add
    CmdItem.Caption = "New Item 1"
    CmdItem.BeginGroup = True
    CmdItem.OnAction = "'" & ThisWorkbook.Name & "'" & "!Macro_One"

    Set MnuEvt = New VBECmdHandler

    Set MnuEvt.EvtHandler = Application.VBE.Events.CommandBarEvents(CmdItem)
    EvtHandlers.Add MnuEvt

'----------------------------------------------------------------
' Now, add the second menu item to the "Tools" menu.
'
    Set CmdItem = .Controls.Add
    CmdItem.Caption = "New Item 2"
    CmdItem.OnAction = "'" & ThisWorkbook.Name & "'" & "!Macro_Two"

    Set MnuEvt = New VBECmdHandler
    Set MnuEvt.EvtHandler = Application.VBE.Events.CommandBarEvents(CmdItem)

    EvtHandlers.Add MnuEvt
End With

End Sub

 

 

This procedure adds two new items to the Tools menu.  The first steps are the same as adding a menu item to the standard Excel menus.  The code 

    Set MnuEvt = New VBECmdHandler

sets the MnuEvt object to a new instance of the VBECmdHandler class. The next line 

    Set MnuEvt.EvtHandler = Application.VBE.Events.CommandBarEvents(CmdItem)

sets the EvtHandler property to the CommandBarEvents object of the VBE for the CmdItem menu item. The EvtHandler  is the object we declared WithEvents in the class module.   These two lines of code create the "bridge" between the menu item CmdItem and the code that will execute when the item is clicked.  

Since we're going to be adding another menu item and event using the same MnuEvt object, we need to save a copy of the current object so that it will not be overwritten.  We do this by adding it to the EvtHandlers  collection.  By doing this, you don't have to declare a separate VBECmdHandler object for each menu item.  This makes the code much easier to maintain, especially when you're adding several menu items in a loop. 

To test this code, create two new macros, Macro_One and Macro_Two, which will be executed when you click the menu items.  For example, 

Sub Macro_One()
    Debug.Print "Macro One"
End Sub
Sub Macro_Two()
    Debug.Print "Macro Two"
End Sub


Since all of the objects that are created in these procedures are within the workbook which created them, the will exist (and therefore your menus will work) only when this workbook is open.  To have these menu items functional regardless of what workbook is open, you may want to put all of these modules and code in an Add-In module that will be loaded whenever Excel is running.  

You can download this a workbook which illustrates this code by clicking here (15KB zip file) . 

 

        
If you'd like to learn more about working with the VBE command bars, I would very highly recommend the book Excel 2000 VBA Programmer's Reference, written by John Green with Stephen Bullen, both Microsoft MVPs well known the regular readers of the Excel newsgroups.  Stephen Bullen has on his web site two add-in modules available for download which go into much more detail than this page and the example file I provide.  For Excel2000, download VBETools2000 (about 234 KB self-extracting file). For Excel97, download VBETools (about 29 KB zip file).  I would also recommend you spend some time learning about the other downloadable files that Stephen has made available on his site.