存档在 ‘Excel菜单与工具栏’ 分类中.

自定义Excel菜单栏技术——表驱动命令栏

在Excel中采用表驱动(table-driven)的方式创建自定义命令栏是一种常用的技术。即在工作表中设置适当的数据,然后利用这些数据来创建菜单,这样既简单又方便。而且,不懂VBA编程的用户也能通过修改工作表中的数据来创建自已的命令栏。
这里介绍一个相对简单的例子,来自于《Mastering Excel 2003 Programming with VBA》。如下图所示的工作表中放置用来创建菜单的数据:
MenuBuilderpic1
现在,需要使用程序来运用MenuBuilder工作表来构建适当的菜单,除了ParentTag列(即A列)外,其他列为CommandBarControl对象的不同属性。ParentTag列用来指定是否创建一个新的菜单、菜单项或子菜单。代码如下:

Option Explicit

Const NA = "N/A"

'列偏移
Const TAG_OFFSET = 1
Const CAPTION_OFFSET = 2
Const TYPE_OFFSET = 3
Const ONACTION_OFFSET = 4
Const BEGINGROUP_OFFSET = 5
Const DESCRIPTION_OFFSET = 6

Sub BuildMenu()
  Dim ws As Worksheet
  Dim rg As Range
  On Error GoTo ErrHandler
  Set ws = ThisWorkbook.Worksheets("MenuBuilder")

'从第二行开始,因为第一行已经包含了列标题
  Set rg = ws.Cells(2, 1)
  Do Until IsEmpty(rg)
  If rg.Value = NA Then
  '新建顶级菜单项
  AddTopLevelItem rg
  Else
  '现有控件的子菜单
  AddSubItem rg
  End If
  '向下移一行
  Set rg = rg.Offset(1, 0)
  Loop

ExitPoint:
  Set rg = Nothing
  Set ws = Nothing
  Exit Sub
ErrHandler:
  Debug.Print Err.Description
  Resume ExitPoint
End Sub

'向工作表菜单栏中添加新菜单项
Private Function AddTopLevelItem(rg As Range) As CommandBarControl
  Dim cbWSMenuBar As CommandBar
  Dim cbc As CommandBarControl
  On Error GoTo ErrHandler
  Set cbWSMenuBar = Application.CommandBars("Worksheet Menu Bar")
  '添加菜单项
  Set cbc = cbWSMenuBar.Controls.Add(msoControlPopup, , , , True)
  cbc.Tag = rg.Offset(0, TAG_OFFSET).Value
  cbc.DescriptionText = rg.Offset(0, DESCRIPTION_OFFSET).Value
  cbc.Caption = rg.Offset(0, CAPTION_OFFSET).Value
  '返回新添加的菜单项
  Set AddTopLevelItem = cbc
ExitPoint:
  Set cbc = Nothing
  Set cbWSMenuBar = Nothing
  Exit Function
ErrHandler:
  Set AddTopLevelItem = Nothing
  Resume ExitPoint
End Function

Private Function AddSubItem(rg As Range) As CommandBarControl
  Dim cbcParent As CommandBarControl
  Dim cbc As CommandBarControl
  On Error GoTo ErrHandler
  '基于父标记定位父菜单
  Set cbcParent = Application.CommandBars.FindControl(, , rg.Value)
  If Not cbcParent Is Nothing Then
  '添加菜单项
  Set cbc = cbcParent.Controls.Add(GetType(rg))
  '确保该菜单项具有一个OnAction值而不是N/A
  If rg.Offset(0, ONACTION_OFFSET).Value <> NA Then
  cbc.OnAction = rg.Offset(0, ONACTION_OFFSET).Value
  End If
  cbc.Tag = rg.Offset(0, TAG_OFFSET).Value
  cbc.DescriptionText = rg.Offset(0, DESCRIPTION_OFFSET).Value
  cbc.Caption = rg.Offset(0, CAPTION_OFFSET).Value
  cbc.BeginGroup = rg.Offset(0, BEGINGROUP_OFFSET).Value
  '返回新添加的控件
  Set AddSubItem = cbc
  Else
  '不能找到父控件-返回无
  Set AddSubItem = Nothing
  End If
ExitPoint:
  Set cbc = Nothing
  Set cbcParent = Nothing
  Exit Function
ErrHandler:
  Debug.Print Err.Description
  Set AddSubItem = Nothing
  Resume ExitPoint
End Function

'将所选的msoControlType枚举转换为值
Private Function GetType(rg As Range) As Long
  Dim sType As String
  sType = rg.Offset(0, TYPE_OFFSET).Value
  Select Case sType
  Case Is = "msoControlPopup"
  GetType = msoControlPopup
  Case Is = "msoControlButton"
  GetType = msoControlButton
  Case Is = "msoControlDropDown"
  GetType = msoControlDropdown
  Case Else '包括N/A
  '默认为msoControlPopup
  GetType = msoControlPopup
  End Select
End Function

'删除标记为"MyMenu2"的控件
Sub DeleteMyMenu2()
  DeleteMenu "MyMenu2"
End Sub

'删除标记为"MyMenu3"的控件
Sub DeleteMyMenu3()
  DeleteMenu "MyMenu3"
End Sub

Private Sub DeleteMenu(sTag As String)
  Dim cbc As CommandBarControl
  Set cbc = Application.CommandBars.FindControl(Tag:=sTag)
  If Not cbc Is Nothing Then
  cbc.Delete
  End If
  Set cbc = Nothing
End Sub

上述代码的主程序是BuildMenu过程,该过程遍历工作表MenuBuilder中A列的单元格,检查其值是否等于N/A,如果等于则调用AddTopLevelItem过程在工作表菜单栏中创建一个新菜单项,如果不等于则调用AddSubItem过程,根据标记查找已存在的菜单项并在其中添加子菜单项。
此外,AddTopLevelItem过程忽略了Type列和OnAction列,并自动添加msoControlPopup类型的控件。AddSubItem过程将检查OnAction列的值,确保其中不会包含值N/A,若包含则不会设置OnAction属性。
最后的三个过程用来删除已创建好的菜单项。
创建的菜单如下图。
MenuBuilderpic2
前面说过,这是一个简单的菜单构建器示例,其中只包括了构建菜单所需的常见的一些属性。您可以添加列并修改相应的代码,使其功能更加强大,例如添加控件的Visible和Enabled属性列。

恢复Excel菜单和工具栏

Technorati 标签: ,

如果您的Excel应用程序的菜单和工具栏无意中搞乱了,例如调整了菜单项的位置、禁用了一些菜单项而又未恢复、删除了一些菜单项等,您想要恢复为默认的状态,这里有一个简便的方法,即删除*.xlb文件。这个文件在下面的目录中:

C:\Documents and Settings\<用户名>\Application Data\Microsoft\Excel

其中,<用户名>代表您计算机上的登录名。对于Excel 2003来说,该文件名为Excel11.xlb。

此时,您不必担心。当您重新开启Excel时,Excel会为您自动重新生成新的.xlb文件。这里的秘密是:Excel将工具栏和菜单栏的配置存储在xlb文件中,当您改变工具栏和菜单栏并退出Excel时,当前的配置将会被保存到xlb文件。如果xlb文件被破坏,那么在Excel启动时可能导致Excel崩溃。此时可以删除xlb文件或者重新命名xlb文件,Excel将创建新的xlb文件。

注:通常情况下,该文件夹是隐藏的,需要更改“文件夹选项”以显示所有的文件和文件夹。

标签: 没有标签

Excel快捷菜单和Excel事件

本文中的示例演示了与事件协同使用的不同的快捷菜单编程技术。
自动添加和删除菜单
如果需要在打开工作簿时修改快捷菜单,则使用Workbook_Open事件。下面的代码存储在ThisWorkbook对象的代码模块中,在打开工作簿时将执行ModifyShortcut过程。
Private Sub Workbook_Open()
    Call ModifyShortcut
End Sub

要使快捷菜单恢复到其修改前的状态,则使用下面的过程。该过程在关闭工作簿之前执行,并且会调用RestoreShortcut过程。
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Call RestoreShortcut
End Sub

但是,这里存在着一个问题,即在用户关闭工作簿时,如果不保存该工作簿,会发生意外情况。在Workbook_BeforeClose事件处理运行之后,Excel会提示“是否保存对工作簿所作的修改?”,此时,如果用户单击“取消”按钮,则工作簿仍然保持打开,但自定义菜单已经被删除了。
对该问题的一种解决方法是绕开Excel的提示,在Workbook_BeforeClose过程中编写代码来询问用户保存该工作簿。下面的代码演示了如何进行操作:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    If Not Me.Saved Then
        Msg = "您想保存对"
        Msg = Msg & Me.Name & "的改变吗?"
        Ans = MsgBox(Msg, vbQuestion + vbYesNoCancel)
        Select Case Ans
            Case vbYes
                Me.Save
            Case vbNo
                Me.Saved = True
            Case vbCancel
                Cancel = True
                Exit Sub
        End Select
    End If
    Call RestoreShortcut
End Sub

上述过程确定是否已保存了工作簿,如果该工作簿已保存,则没有问题,执行RestoreShortcut过程,然后关闭该工作簿。但是如果还没有保存该工作簿,则该过程显示一条复制Excel正常显示时的消息框。如果用户单击“是”,则保存工作簿,并删除菜单,然后关闭工作簿。如果用户单击“否”,则代码将Workbook对象的Saved属性设置为True(实际上没有保存该文件)并删除菜单。如果用户单击“取消”,则BeforeClose事件被取消,过程结束而不会恢复快捷菜单。

禁用或者隐藏快捷菜单项
当禁用某菜单项时,其文本显示为暗灰色的阴影,单击该菜单项时没有任何反应。当隐藏某菜单项时,在快捷菜单中不会出现该菜单项。当然,您可以编写VBA代码来启用或禁用快捷菜单项。同样,您可以编写代码来隐藏快捷菜单项。关键是要使用正确的事件。
例如,下面的代码在激活工作表Sheet2时禁用Change Case快捷菜单项(该菜单项已添加到单元格快捷菜单中,参见“使用VBA自定义Excel 2007快捷菜单”),该过程位于Sheet2代码模块中:
Private Sub Worksheet_Activate()
    CommandBars("Cell").Controls("Change Case").Enabled = False
End Sub

要在工作表Sheet2失活时(即不为当前活动工作表时)启用该菜单项,添加下面的过程。其效果是,除了激活工作表Sheet2外,Change Case菜单项在所有其它情形下均可用。
Private Sub Worksheet_Deactivate()
    CommandBars("Cell").Controls("Change Case").Enabled = True
End Sub
要隐藏该菜单项而不是禁用它,只需使用Visible属性代替Enabled属性。

创建一个上下文相关的快捷菜单
可以创建一个全新的快捷菜单,并且在响应特定的事件时显示该菜单。下面的代码创建一个名为MyShortcut的快捷菜单,包含有6个菜单项,分别设置其OnAction属性来执行简单的过程,即分别显示“单元格格式”对话框中的某一选项卡(参见下图1)。
ExcelMenuAndEvent
图1:一个新的快捷菜单,仅当用户右击工作表阴影区域中的某单元格时出现
Sub CreateShortcut()
    Dim myBar As CommandBar
    Dim myItem As CommandBarControl
    
    '   若已存在该菜单,则删除
    DeleteShortcut
    
    '   添加一个新菜单
    Set myBar = CommandBars.Add _
      (Name:="MyShortcut", Position:=msoBarPopup, Temporary:=True)
    
    '   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = "&Number Format..."
        .OnAction = "ShowFormatNumber"
        .FaceId = 1554
    End With
        
    '   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = "&Alignment..."
        .OnAction = "ShowFormatAlignment"
        .FaceId = 194
    End With
        
    '   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = "&Font..."
        .OnAction = "ShowFormatFont"
        .FaceId = 309
    End With
    '   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = "&Borders..."
        .OnAction = "ShowFormatBorder"
        .FaceId = 149
        .BeginGroup = True
    End With
    
    '   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = "&Fill..."
        .OnAction = "ShowFormatPatterns"
        .FaceId = 687
    End With
    
    '   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = "&Protection..."
        .OnAction = "ShowFormatProtection"
        .FaceId = 225
    End With
End Sub

创建了快捷菜单后,可以通过使用ShowPopup方法来显示该菜单。下面的过程,位于Worksheet对象的代码模块中,当用户右击某单元格时执行:
Private Sub Worksheet_BeforeRightClick _
  (ByVal Target As Excel.Range, Cancel As Boolean)
    If Union(Target.Range("A1"), Range("data")).Address = _
      Range("data").Address Then
        CommandBars("MyShortcut").ShowPopup
        Cancel = True
    End If
End Sub

当用户右击时,如果活动单元格在名为data的单元格区域内,则显示MyShortcut菜单。设置Cancel参数为True,确保不显示正常的快捷菜单。注意,微型(mini)工具栏也没有显示。
下面是创建快捷菜单的过程代码中对应的所要执行的宏:
Sub ShowFormatNumber()
    'Application.Dialogs(xlDialogFormatNumber).Show
    CommandBars.ExecuteMso ("FormatCellsNumberDialog")
End Sub
Sub ShowFormatAlignment()
    'Application.Dialogs(xlDialogAlignment).Show
    CommandBars.ExecuteMso ("CellAlignmentOptions")
End Sub

Sub ShowFormatFont()
    'Application.Dialogs(xlDialogFormatFont).Show
    CommandBars.ExecuteMso ("FormatCellsFontDialog")
End Sub

Sub ShowFormatBorder()
    'Application.Dialogs(xlDialogBorder).Show
    CommandBars.ExecuteMso ("BordersMOreDialog")
End Sub

Sub ShowFormatPatterns()
    '(没有ExecuteMso方法,因此使用旧样式)
    Application.Dialogs(xlDialogPatterns).Show
End Sub

Sub ShowFormatProtection()
    '(没有ExecuteMso方法,因此使用旧样式)
    Application.Dialogs(xlDialogCellProtection).Show
End Sub

Sub DeleteShortcut()
    On Error Resume Next
    CommandBars("MyShortcut").Delete
End Sub
也可以使用鼠标来显示该快捷菜单,创建一个简单的过程,并通过“宏”对话框中的“选项”按钮分配一个快捷键。
Sub ShowMyShortcutMenu()
'   Ctrl+Shift+M快捷键
    CommandBars("MyShortcut").ShowPopup
End Sub

标签: 没有标签

使用VBA自定义Excel 2007快捷菜单

本文将展示一些操作Excel快捷菜单的VBA代码实例,您可以修改这些例子以满足您的需要。本文中的大部分内容也适用于Excel以前的版本。
重置快捷菜单
Reset方法恢复某快捷菜单到其默认状态,例如,下面的过程恢复单元格(Cell)快捷菜单到其标准状态:
Sub ResetCellMenu()
    CommandBars("Cell").Reset
End Sub

Excel有两个名为Cell的快捷菜单,上面的代码仅恢复第一个(即索引值为38)的Cell快捷菜单。为恢复第二个Cell快捷菜单,使用索引值(41)代替其名称。
下面的过程恢复所有的内置工具栏到其初始状态:
Sub ResetAll()
    Dim cbar As CommandBar
    For Each cbar In Application.CommandBars
        If cbar.Type = msoBarTypePopup Then
            cbar.Reset
            cbar.Enabled = True
        End If
    Next cbar
End Sub

注意,如果在您的应用程序中添加项目到某快捷菜单中,最好在关闭应用程序时分别移除这些项目。如果简单地恢复快捷菜单,将会删除由其它应用程序所定制的快捷菜单。
禁用快捷菜单
Enabled属性可以让您禁用整个快捷菜单。例如,可以设置该属性后,在右键单击某单元格时不再显示正常的快捷菜单,下面的语句禁用Cell快捷菜单:

Application.CommandBars("Cell").Enabled = False

要重新启用该快捷菜单,简单地设置其Enabled属性为True。
如果想要禁用所有的快捷菜单,使用下面的过程:
Sub DisableAllShortcutMenus()
    Dim cb As CommandBar
    For Each cb In CommandBars
        If cb.Type = msoBarTypePopup Then _
          cb.Enabled = False
    Next cb
End Sub

注意,禁用的快捷菜单将会在所有会话中起作用,因此,在关闭Excel之前可能想要恢复快捷菜单。要恢复快捷菜单,将前面过程中的Enabled属性设置为True。
禁用快捷菜单项
您可能想在应用程序运行时,禁用某快捷菜单中的一个或多个快捷菜单项。当禁用某菜单项时,其文本显示为亮灰色,单击它时不会有任何效果。下面的过程从行或列快捷菜单中禁用“隐藏”菜单项:
Sub DisableHideMenuItems()
    CommandBars("Column").Controls("隐藏(H)").Enabled = False
    CommandBars("Row").Controls("隐藏(H)").Enabled = False
End Sub

添加一个新项到单元格快捷菜单中
下面的AddToShortcut过程添加一个新菜单项到单元格快捷菜单中:Toggle Word Wrap。Excel有两个单元格快捷菜单,下面的过程修改正常的右击菜单,但不修改显示在分页预览模式下的右击菜单。
Sub AddToShortCut()
    '添加一个菜单项到单元格快捷菜单中
    Dim Bar As CommandBar
    Dim NewControl As CommandBarButton
    DeleteFromShortcut
    Set Bar = CommandBars("Cell")
    Set NewControl = Bar.Controls.Add _
      (Type:=msoControlButton, _
      temporary:=True)
    With NewControl
        .Caption = "Toggle &Word Wrap"
        .OnAction = "ToggleWordWrap"
        .Picture = Application.CommandBars.GetImageMso _
          ("WrapText", 16, 16)
        .Style = msoButtonIconAndCaption
    End With
End Sub

图1展示了在右击单元格后显示的新菜单项。
AddNewMenuItem
图1:带有自定义菜单项的单元格快捷菜单
上面的过程中,在声明了一组变量后调用DeleteFromShortcut过程(参见下面)。这条语句确保在单元格快捷菜单中仅显示一次Toggle Word Wrap菜单项,注意该菜单项带下划线的热键是W,不是T,那是因为已准备在Cut菜单项中使用T。
设置Picture属性为Wrap Text命令来引用使用在功能区中的图像,参见“”中关于在功能区命令中使用图像的更多信息。
下面的宏通过OnAction属性指定,在选择该菜单项时执行。这里,宏的名称为ToggleWordWrap:
Sub ToggleWordWrap()
    CommandBars.ExecuteMso ("WrapText")
End Sub

这个过程简单地执行功能区中的“自动换行”命令。
注意,在修改快捷菜单后,所作的修改将一直保留。换句话说,所修改的快捷菜单在关闭包含该VBA代码的工作簿时不会自已恢复。因此,如果编写代码来修改某快捷菜单,几乎总要编写代码来恢复修改所产生的影响。
DeleteFromShortcut过程从单元格快捷菜单中删除新的菜单项。
Sub DeleteFromShortcut()
    On Error Resume Next
    CommandBars("Cell").Controls _
      ("Toggle &Word Wrap").Delete
End Sub

在一些情况下,想要自动地添加和删除增加的快捷菜单:当打开工作簿时添加快捷菜单项,在关闭工作簿时删除该菜单项。只需要将这两个事件过程添加到ThisWorkbook代码模块:
Private Sub Workbook_Open()
    Call AddToShortCut
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Call DeleteFromShortcut
End Sub

Workbook_Open过程在打开工作簿时执行,Workbook_BeforeClose过程在关闭工作簿之前执行。
注意,添加到快捷菜单中的菜单项不只是在创建菜单项的工作簿可用,在所有工作簿中都是可用的。
添加子菜单到快捷菜单中
本节中的示例将添加带有三个选项的子菜单到快捷菜单中。事实上,添加了子菜单到6个快捷菜单中。图2展示右击一行之后的工作表,子菜单项中的每一个都执行一个宏,来改变所选单元格中的文本。
SubMenuItem
图2:这个快捷菜单有一个带有三个子菜单项的子菜单
--------------------------------------------
查找FaceID图像
显示在快捷菜单项中的图标由两个属性设置之一来确定:

  • Picture:该选项可以使用功能区中的imageMso。
  • FaceID:这是最容易的选项,因为FaceID属性只是一个数字值,代表几百个图像中的一个。

但是,如何查找与特定FaceID图像一致的数值呢?Excel没有提供方法,John Walkenbach创建了一个工具工作簿,可以单击此处下载,并参见“在Excel 2007中自定义菜单”。您只需输入开始和结束的FaceID数字,单击按钮后,将会在工作表中显示图像。每个图像有一个与其FaceID值相一致的名称。
FaceID
--------------------------------------------
下面的代码创建了子菜单及其菜单项:
Sub AddSubmenu()
'   添加一个子菜单到6个快捷菜单中
    Dim Bar As CommandBar
    Dim NewMenu As CommandBarControl
    Dim NewSubmenu As CommandBarButton
    Dim cbIndex As Long
    DeleteSubMenu
    For cbIndex = 36 To 41
        Set Bar = CommandBars(cbIndex)
'       添加子菜单
        Set NewMenu = Bar.Controls.Add _
            (Type:=msoControlPopup, _
             temporary:=True)
        NewMenu.Caption = "Ch&ange Case"
        NewMenu.BeginGroup = True
'       添加第一个子菜单项
        Set NewSubmenu = NewMenu.Controls.Add _
          (Type:=msoControlButton)
        With NewSubmenu
            .FaceId = 38
            .Caption = "&Upper Case"
            .OnAction = "MakeUpperCase"
        End With
'       添加第二个子菜单项
        Set NewSubmenu = NewMenu.Controls.Add _
          (Type:=msoControlButton)
        With NewSubmenu
            .FaceId = 40
            .Caption = "&Lower Case"
            .OnAction = "MakeLowerCase"
        End With
'       添加第三个子菜单项
        Set NewSubmenu = NewMenu.Controls.Add _
          (Type:=msoControlButton)
        With NewSubmenu
            .FaceId = 476
            .Caption = "&Proper Case"
            .OnAction = "MakeProperCase"
        End With
    Next cbIndex
End Sub

AddSubmenu过程使用了一个循环来修改索引值在36和41之间的6个CommandBar对象。所添加的子菜单,其Type属性是msoControlPopup,然后添加了三个子菜单项,每一个子菜单项都有一个不同的OnAction属性。
所调用的DeleteSubMenu过程为:
Sub DeleteSubMenu()
    On Error Resume Next
    Dim Bar As CommandBar
    Dim NewMenu As CommandBarControl
    Dim cbIndex As Long
    For cbIndex = 36 To 41
        Set Bar = CommandBars(cbIndex)
'       删除子菜单
      Bar.Controls _
        ("Ch&ange Case").Delete
    Next cbIndex
End Sub

CommandBar对象介绍

CommandBar对象代表三个Excel用户界面元素:

  • 自定义工具栏
  • 自定义菜单
  • 自定义(右键)快捷菜单

在Excel 2007中,CommandBar对象出现在一个相当奇怪的位置。如果编写定制菜单或工具栏的VBA代码,Excel会拦截代码并忽略一些命令,定制的菜单和工具栏将出现在加载项选项卡中的菜单命令或自定义工具栏组中。为便于应用,Excel 2007中的CommandBar对象仅限制在快捷菜单操作中。
本文将提供一些关于CommandBars的背景信息。
CommandBar类型
Excel支持三种类型的CommandBars,通过其Type属性来区分。而Type属性是下面的三个值之一:

  • msoBarTypeNormal:工具栏(Type = 0)
  • msoBarTypeMenuBar: 菜单栏(Type = 1)
  • msoBarTypePopUp: 快捷菜单(Type = 2)

虽然在Excel 2007中没有使用工具栏和菜单栏,但它们仍然被包含于对象模型中,以便于与老版本的Excel相兼容。但是,试图在Excel 2007中显示类型为0或1的命令栏是无效的。例如,在Excel 2003中,下面的语句显示标准工具栏:

CommandBars("Standard").Visible = True

但在Excel 2007中,该语句将被忽略。下面专门介绍类型为2的命令栏(快捷菜单)。
列出快捷菜单
Excel 2007有65个快捷菜单,您可以运行下面的ShowShortcutMenuNames过程,遍历命令栏,如果Type属性为msoBarTypePopUp(内置的常量值为2),则在工作表中显示命令栏的索引值和名称。
Sub ShowShortcutMenuNames()
    Dim Row As Long
    Dim cbar As CommandBar
    Row = 1
    For Each cbar In CommandBars
        If cbar.Type = msoBarTypePopup Then
            Cells(Row, 1) = cbar.Index
            Cells(Row, 2) = cbar.Name
            Row = Row + 1
        End If
    Next cbar
End Sub

图1显示了该过程输出结果的一部分。
ListShortcutMenu
图1:一个简单的宏来生成所有快捷菜单的列表
引用命令栏
可以通过Index属性或Name属性引用一个特定的CommandBar对象,例如,下面的两个语句都引用在Excel桌面(Excel中没有打开任何文档时)中单击右键时的快捷菜单:

Application.CommandBars (47)

Application.CommandBars("Desktop")

CommandBars集合是Application对象的一个成员,在标准VBA模块或工作表模块中引用这个集合时,可以忽略对Application对象的引用。例如,下面的语句显示CommandBars集合中索引值为47的对象的名称:

MsgBox CommandBars(47).Name

在ThisWorkbook对象代码模块中引用CommandBars集合时,必须在其前面加上Application对象,如:

MsgBox Application.CommandBars(47).Name

注意,在不同的Excel版本中,Index值不总是保持不变。
引用命令栏中的控件
一个CommandBar对象包含Control对象,该对象是按钮或菜单。可以通过其Index属性或Caption属性来引用某控件。下面是一个简单的示例过程,显示单元格快捷菜单中第一个菜单项的标题:
Sub ShowCaption()
    MsgBox Application.CommandBars("Cell"). _
       Controls(1).Caption
End Sub

下面的过程显示在工作表选项卡中单击右键时出现的快捷菜单中每个控件的Caption属性(该快捷菜单名为Ply):
Sub ShowCaptions()
    Dim txt As String
    Dim ctl As CommandBarControl
    For Each ctl In CommandBars("Ply").Controls
        txt = txt & ctl.Caption & vbNewLine
    Next ctl
    MsgBox txt
End Sub

执行该过程后的结果如图2所示。
CellShortcutMenuCaption
图2:显示控件的Caption属性
在一些情况下,某快捷菜单中的Control对象包含其它的Control对象。例如,单元格右键菜单中的“筛选”控件包含其它控件,“筛选”控件是一个子菜单,而另外的项目是菜单项。
-----------------------
查找控件
如果所编写的代码将在不同的语言版本的Excel中使用,则应避免使用Caption属性来访问某特定的快捷菜单项。Caption属性随语言的不同而不同,因此在英文版本的Excel中编写的代码可能在其它语言的Excel版本中运行失败。
取而代之的是,应该与控件的ID一起使用FindControl方法(它们将独立于Excel的语言版本)。例如,假设想禁用工作表选项卡快捷菜单中的“重命名”菜单,如果该工作簿仅由Excel英文版本的用户使用,则下面的语句将正常运行:

CommandBars("Ply").Controls("Rename").Enabled = False

为了确保该命令在非英语版本的Excel中也能工作,需要知道该控件的ID,上面的语句将告诉您其ID是889:

MsgBox CommandBars("Ply").Controls("重命名(R)").ID

然后,来禁用该控件,使用下面的语句:

CommandBars.FindControl(ID:=889).Enabled = False

命令栏的名称在各语言版本的Excel中都是一致的,因此,对CommandBars("Desktop")的引用将总会正常运行。
-----------------------
下面的语句显示“筛选”子菜单中的第一个子菜单项:

MsgBox CommandBars("Cell").Controls("筛选(E)").Controls(1).Caption

命令栏控件的属性
命令栏控件有一些属性,来确定控件的外观和状态。下面包含了命令栏控件的一些最常用的属性:

  • Caption: 控件中显示的文本。如果该控年仅显示一个图像,则为鼠标悬浮在该控件上时的标题文字。
  • ID: 用来识别控件的一个独立的数字。
  • FaceID: 代表显示在控件文本旁边的图形图像的数字。
  • Type: 一个值,用来确定控件是按钮(msoControlButton)还是子菜单 (msoControlPopup)。
  • Picture: 显示在控件文本旁边的图形图像。
  • BeginGroup: 值为True时将在控件前面显示一个分隔条。
  • OnAction: 用户单击控件时执行的VBA宏名称。
  • BuiltIn: 如果该控件是Excel内置控件则为True。
  • Enabled: 如果可以单击控件则为True。
  • Visible: 如果控件可见则为True。一些快捷菜单包含了隐藏的控件。
  • ToolTipText: 用户移动鼠标指针到控件之上时出现的文本(对快捷菜单是不可用的)

显示所有的快捷菜单项
下面的ShowShortcutMenuItems过程创建一个表,列出了每个快捷菜单中的所有第一层次控件。对每个控件,该表包括了快捷菜单的Index和Name以及ID、Caption、Type、Enabled和Visible属性值。
Sub ShowShortcutMenuItems()
    Dim Row As Long
    Dim Cbar As CommandBar
    Dim ctl As CommandBarControl
    Range("A1:G1") = Array("Index", "Name", "ID", "Caption", _
      "Type", "Enabled", "Visible")
    Row = 2
    Application.ScreenUpdating = False
    For Each Cbar In Application.CommandBars
      If Cbar.Type = 2 Then
        For Each ctl In Cbar.Controls
            Cells(Row, 1) = Cbar.Index
            Cells(Row, 2) = Cbar.Name
            Cells(Row, 3) = ctl.ID
            Cells(Row, 4) = ctl.Caption
            If ctl.Type = 1 Then
                Cells(Row, 5) = "Button"
            Else
                Cells(Row, 5) = "Submenu"
            End If
            Cells(Row, 6) = ctl.Enabled
            Cells(Row, 7) = ctl.Visible
           Row = Row + 1
       Next ctl
     End If
    Next Cbar
End Sub

图3显示了过程运行后的一部分结果:
ListAllShortcutMenu
图3:列出所有快捷菜单项
如果运行ShowShortcutMenuItems宏,则会看到有一些快捷菜单包含隐藏或禁用的控件,它们代表在当前上下文环境中不可用的项目。
示例工作簿参见:show shortcut menu items.xlsm