19.1 掌握好命令栏

代码清单19.1: 列出申请CommandBar

 

代码
'代码清单19.1: 列出申请CommandBar
'
List all of the command bars on a worksheet named inventory
Sub Inventory()
    
Dim cb As CommandBar
    
Dim rg As Range
    
Set rg = ThisWorkbook.Worksheets("Inventory").Cells(21)
    
    
'loop through all the command bars in excel
    For Each cb In Application.CommandBars
        rg.Value 
= cb.Name
        rg.Offset(
01).Value = cb.Index
        rg.Offset(
02).Value = cb.BuiltIn
        rg.Offset(
03).Value = cb.Enabled
        rg.Offset(
04).Value = cb.Visible
        rg.Offset(
05).Value = TranslateCommandBarType(cb.Type)
        rg.Offset(
06).Value = TranslateCommandBarPosition(cb.Position)
        rg.Offset(
07).Value = cb.Controls.Count
            
        
Set rg = rg.Offset(10)
    
Next
    
    
Set rg = Nothing
    
Set cb = Nothing
End Sub

'translates a msoBarType enumeration into a text description
'
of the bar type.
Function TranslateCommandBarType(vType As MsoBarType) As String
    
Dim sType As String
    
    
Select Case vType
        
Case MsoBarType.msoBarTypeMenuBar
            sType 
= "Menu Bar"
        
Case MsoBarType.msoBarTypeNormal
            sType 
= "Normal"
        
Case MsoBarType.msoBarTypePopup
            sType 
= "Popup"
        
Case Else
            sType 
= "Unknown type"
    
End Select
    TranslateCommandBarType 
= sType
End Function

'translates a msoBarPosition enumeration into a text description
'
of the bar position
Function TranslateCommandBarPosition(vType As MsoBarPosition) As String
    
Dim sPosition As String
    
    
Select Case vType
        
Case MsoBarPosition.msoBarBottom
            sPosition 
= "Bottom"
        
Case MsoBarPosition.msoBarFloating
            sPosition 
= "Floating"
        
Case MsoBarPosition.msoBarLeft
            sPosition 
= "Left"
        
Case MsoBarPosition.msoBarMenuBar
            sPosition 
= "MenuBar"
        
Case MsoBarPosition.msoBarPopup
            sPosition 
= "Popup"
        
Case MsoBarPosition.msoBarRight
            sPosition 
= "Right"
        
Case MsoBarPosition.msoBarTop
            sPosition 
= "Top"
        
Case Else
            sType 
= "Unknown Position"
    
End Select
    TranslateCommandBarPosition 
= sPosition
End Function

 

代码清单19.2: 生效一个CommandBar

 

代码
'代码清单19.2: 生效一个CommandBar
'
Tests CommandBarExists and ShowCommandBar
Sub TestCommandBarUtilities()
    Debug.Print CommandBarExists(
"Worksheet Menu Bar")
    Debug.Print CommandBarExists(
"Formatting")
    Debug.Print CommandBarExists(
"Not a command bar")
    
    ShowCommandBar 
"Borders"True
End Sub

'Determines if a given command bar name exists
Function CommandBarExists(sName As StringAs Boolean
    
Dim s As String
    
On Error GoTo bWorksheetExistsErr
    
    s 
= Application.CommandBars(sName).Name
    CommandBarExists 
= True
    
Exit Function
bWorksheetExistsErr:
    CommandBarExists 
= False
End Function

'Shows or hides a command bar. you do not need
'
to validate sName before using this procedure.
'
Depends on CommandBarExists function.
Sub ShowCommandBar(sName As String, bShow As Boolean)
    
If CommandBarExists(sName) Then
        Application.CommandBars(sName).Visible 
= bShow
    
End If
End Sub

 

 

19.2 CommandBar反应

代码清单19.3: 检查一个CommandBar

 

代码
'代码清单19.3: 检查一个CommandBar
Sub InspectCommandBar(cb As CommandBar, rgOutput As Range)
    DisplayGeneralInfo cb, rgOutput
    
Set rgOutput = rgOutput.End(xlDown).Offset(20)
    DisplayControlDetail cb, rgOutput
    
End Sub

Sub DisplayGeneralInfo(cb As CommandBar, rgOutput As Range)
    rgOutput.Value 
= "Name: "
    rgOutput.Offset(
01).Value = cb.Name
    
    rgOutput.Offset(
10).Value = "Index: "
    rgOutput.Offset(
11).Value = cb.Index
    
    rgOutput.Offset(
20).Value = "Built In: "
    rgOutput.Offset(
21).Value = cb.BuiltIn
    
    rgOutput.Offset(
30).Value = "Enabled: "
    rgOutput.Offset(
31).Value = cb.Enabled
    
    rgOutput.Offset(
40).Value = "Visible: "
    rgOutput.Offset(
41).Value = cb.Visible
    
    rgOutput.Offset(
50).Value = "Type: "
    rgOutput.Offset(
51).Value = TranslateCommandBarType(cb.Type)
    
    rgOutput.Offset(
60).Value = "Position: "
    rgOutput.Offset(
61).Value = TranslateCommandBarPosition(cb.Position)
    
    rgOutput.Offset(
70).Value = "Control Count: "
    rgOutput.Offset(
71).Value = cb.Controls.Count
    
    
With rgOutput.Resize(81)
        .Font.Bold 
= True
        .HorizontalAlignment 
= xlRight
    
End With
End Sub

Sub DisplayControlDetail(cb As CommandBar, rgOutput As Range)
    
Dim cbc As CommandBarControl
    
    
On Error Resume Next
    
    
    
'make column header
    rgOutput.Value = "Description"
    rgOutput.Offset(
01).Value = "Caption"
    rgOutput.Offset(
02).Value = "Index"
    rgOutput.Offset(
03).Value = "Built In?"
    rgOutput.Offset(
04).Value = "Enabled?"
    rgOutput.Offset(
05).Value = "Visible?"
    rgOutput.Offset(
06).Value = "Priority Dropped?"
    rgOutput.Offset(
07).Value = "Priority"
    rgOutput.Offset(
08).Value = "Type"
    rgOutput.Offset(
09).Value = "Control Count"
    rgOutput.Offset(
010).Font.Bold = True
    
    
Set rgOutput = rgOutput.Offset(10)
    
'Get control detail
    For Each cbc In cb.Controls
        
        rgOutput.Value 
= Replace(cbc.Caption, "&""")
        rgOutput.Offset(
01).Value = cbc.Caption
        rgOutput.Offset(
02).Value = cbc.Index
        rgOutput.Offset(
03).Value = cbc.BuiltIn
        rgOutput.Offset(
04).Value = cbc.Enabled
        rgOutput.Offset(
05).Value = cbc.Visible
        rgOutput.Offset(
06).Value = cbc.IsPriorityDropped
        rgOutput.Offset(
07).Value = cbc.Priority
        rgOutput.Offset(
08).Value = TranslateCommandBarType(cbc.Type)
        rgOutput.Offset(
09).Value = cbc.Controls.Count
        
        
Set rgOutput = rgOutput.Offset(10)
    
Next
    
    
'Clean up.
    Set cbc = Nothing
End Sub

'Translates a MsoControlType enumeration into a text description of the control type.
Function TranslateControlType(vType As MsoControlType) As String
    
Dim sType As String
    
    
Select Case vType
        
Case MsoControlType.msoControlActiveX
            sType 
= "ActiveX"
        
Case MsoControlType.msoControlAutoCompleteCombo
            sType 
= "AutoCompleteCombo"
        
Case MsoControlType.msoControlButton
            sType 
= "Button"
        
Case MsoControlType.msoControlButtonDropdown
            sType 
= "ButtonDropdown"
        
Case MsoControlType.msoControlButtonPopup
            sType 
= "ButtonPopup"
        
Case MsoControlType.msoControlComboBox
            sType 
= "ComboBox"
        
Case MsoControlType.msoControlCustom
            sType 
= "Custom"
        
Case MsoControlType.msoControlDropdown
            sType 
= "Dropdown"
        
Case MsoControlType.msoControlEdit
            sType 
= "Edit"
        
Case MsoControlType.msoControlExpandingGrid
            sType 
= "ExpandingGrid"
        
Case MsoControlType.msoControlGauge
            sType 
= "Gauge"
        
Case MsoControlType.msoControlGenericDropdown
            sType 
= "GenericDropdown"
        
Case MsoControlType.msoControlGraphicCombo
            sType 
= "GraphicCombo"
        
Case MsoControlType.msoControlGraphicDropdown
            sType 
= "GraphicDropdown"
        
Case MsoControlType.msoControlGraphicPopup
            sType 
= "GraphicPopup"
        
Case MsoControlType.msoControlGrid
            sType 
= "Label"
        
Case MsoControlType.msoControlLabel
            sType 
= "Label"
        
Case MsoControlType.msoControlLabelEx
            sType 
= "LabelEx"
        
Case MsoControlType.msoControlOCXDropdown
            sType 
= "OCXDropdown"
        
Case MsoControlType.msoControlPane
            sType 
= "Pane"
        
Case MsoControlType.msoControlPopup
            sType 
= "Popup"
        
Case MsoControlType.msoControlSpinner
            sType 
= "Spinner"
        
Case MsoControlType.msoControlSplitButtonMRUPopup
            sType 
= "SplitButtonMRUPopup"
        
Case MsoControlType.msoControlSplitButtonPopup
            sType 
= "SplitButtonPopup"
        
Case MsoControlType.msoControlSplitDropdown
            sType 
= "SplitDropdown"
        
Case MsoControlType.msoControlSplitExpandingGrid
            sType 
= "SplitExpandingGrid"
        
Case MsoControlType.msoControlWorkPane
            sType 
= "WorkPane"
        
Case Else
            sType 
= "unkown control type"
    
End Select
    TranslateControlType 
= sType
End Function

 

代码清单19.4: 将组合框键入到InspectCommandBar程序

 

代码
'代码清单19.4: 将组合框键入到InspectCommandBar程序
Sub choCommandBars_Change()
    
'make sure the correct worksheet is active, changing
    'the name of other worksheets can trigger
    'this event unexpectedly.
    If ActiveSheet.Name = Me.Name Then
        
'clear the details associated with the
        'previous command bar
        Me.Range("A14:J65536").ClearContents
        
        
'inspect the command bar
        InspectCommandBar Application.CommandBars(Me.Range("CommandBar").Value), Me.Range("A4")
        
    
End If
End Sub

 

 

19.3 可以弯曲的CommandBarControl对象

代码清单19.5: 使用FindControls查找可见控件

 

代码
'代码清单19.5: 使用FindControls查找可见控件
Sub ShowVisibleControls()
    FindVisibleControls ThisWorkbook.Worksheets(
"FindControl").Range("FoundControls").Offset(10)
End Sub

'displays information on all visible controls
Sub FindVisibleControls(rg As Range)
    
Dim ctrls As CommandBarControls
    
Dim ctrl As CommandBarControl
    
    
Set ctrls = Application.CommandBars.FindControls(, , , True)
    
    
For Each ctrl In ctrls
        rg.Value 
= ctrl.Parent.Name
        rg.Offset(
01).Value = ctrl.Caption
        rg.Offset(
02).Value = ctrl.Index
        rg.Offset(
03).Value = ctrl.ID
        rg.Offset(
04).Value = ctrl.Enabled
        rg.Offset(
05).Value = ctrl.Visible
        rg.Offset(
06).Value = ctrl.IsPriorityDropped
        rg.Offset(
07).Value = TranslateControlType(ctrl.Type)
        
        
Set rg = rg.Offset(10)
    
Next
    
    
Set ctrl = Nothing
    
Set ctrls = Nothing
End Sub

 

 

19.4 精心编制自定义命令栏

代码清单19.6: 创建一个菜单栏

 

代码
'代码清单19.6: 创建一个菜单栏
Sub AddMenuItemExample()
    
Dim cbWSMenuBar As CommandBar
    
Dim cbc As CommandBarControl
    
    
Set cbWSMenuBar = Application.CommandBars("Worksheet Menu Bar")
    
    
'Add a menu item
    Set cbc = cbWSMenuBar.Controls.Add(Type:=msoControlPopup, temporary:=True)
    
    
'set its tag so it can be easily found and referred to in VBA
    cbc.Tag = "MyMenu"
    
    
With cbc
        .Caption 
= "&My Menu"
        
        
With .Controls.Add(Type:=msoControlButton, temporary:=True)
            .Caption 
= "Item &1"
            .OnAction 
= "Thisworkbook.sayhello"
            .Tag 
= "Item 1"
        
End With
        
        
With .Controls.Add(Type:=msoControlButton, temporary:=True)
            .Caption 
= "Item &2"
            .OnAction 
= "Thisworkbook.sayhello"
            .Tag 
= "Item 2"
        
End With        
        
        
With .Controls.Add(Type:=msoControlButton, temporary:=True)
            .Caption 
= "Item &3"
            .OnAction 
= "Thisworkbook.sayhello"
            .Tag 
= "Item 3"
        
End With
        
        
With .Controls.Add(Type:=msoControlButton, temporary:=True)
            .Caption 
= "Item &4"
            .OnAction 
= "Thisworkbook.sayhello"
            .BeginGroup 
= True
            .Tag 
= "Item 4"
        
End With
        
        
With .Controls.Add(Type:=msoControlButton, temporary:=True)
            .Caption 
= "Item &5"
            .OnAction 
= "Thisworkbook.sayhello"
            .Tag 
= "Item 5"
            .BeginGroup 
= True
        
End With        
        
        
With .Controls.Add(Type:=msoControlButton, temporary:=True)
            .Caption 
= "Item &6"
            .OnAction 
= "Thisworkbook.sayhello"
            .Tag 
= "Item 6"
        
End With        
    
End With
End Sub

Sub SayHello()
    
MsgBox "Hello", vbOKOnly
End Sub

'Restores the worksheet Menu bar to its native state
Sub ResetCommandBar()
    Application.CommandBars(
"Worksheet Menu Bar").Reset    
End Sub

 

代码清单19.7: 控制一个CommandBarControl的可见性

 

代码
'代码清单19.7: 控制一个CommandBarControl的可见性
Sub SetVisibilityExample()
    
Dim vResponse As Variant
    
    vResponse 
= MsgBox("do you want to show mymenu item?", vbYesNo)
    
    
If vResponse = vbYes Then
        SetControlVisibility 
"MyMenu"True
    
Else
        SetControlVisibility 
"MyMenu"False
    
End If    
End Sub

Sub SetControlVisibility(sTag As String, IsVisible As Boolean)
    
Dim cbc As CommandBarControl
    
Set cbc = Application.CommandBars.FindControl(, , sTag)
    
    
If Not cbc Is Nothing Then
        cbc.Visible 
= IsVisible
    
End If
    
    
Set cbc = Nothing
End Sub

 

代码清单19.8: 基于工作表菜单构件过程

 

代码
'代码清单19.8: 基于工作表菜单构件过程
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("Menu Builder")
    
    
'start on second row because the first row
    'contains column headers
    Set rg = ws.Cells(21)
    
    
Do Until IsEmpty(rg)
        
If rg.Value = NA Then
            
'new top level menu item
            AddTopLevelItem rg
        
Else
            
'sub-item of existing control
            AddSubItem rg
        
End If
        
        
'move down to the next row
        Set rg = rg.Offset(10)
    
Loop
    
ExitPoint:
    
Set rg = Nothing
    
Set ws = Nothing
    
Exit Sub
ErrHandler:
    Debug.Print Err.Description
    
Resume ExitPoint
End Sub

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")
    
    
'Add a menu item
    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
    
    
'return the newly added menu item
    Set AddTopLevelItem = cbc

ExitPoint:
    
Set cbc = Nothing
    
Set cbWSMenuBar = Nothing
    
Exit Function
ErrHandler:
    
Set AddTopLevelItem = Nothing
    
Resume ExitPoint
End Function

Function AddSubItem(rg As Range) As CommandBarControl
    
Dim cbcParent As CommandBarControl
    
Dim cbc As CommandBarControl
    
    
On Error GoTo ErrHandler
    
    
'Locate parent based on parent tag
    Set cbcParent = Application.CommandBars.FindControl(, , rg.Value)
    
    
If Not cbcParent Is Nothing Then
    
'add a menu item
    Set cbc = cbcParent.Controls.Add(GetType(rg))
    
    
'make sure the item has an OnAction value
    'other than na.
    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
    
    
'return the newly added control
    Set AddSubItem = cbc
    
Else
    
'can't find parent control - return nothing
    Set AddSubItem = Nothing
    
End If
    
ExitPoint:
    
Set cbc = Nothing
    
Set cbcParent = Nothing
    
Exit Function
ErrHandler:
    Debug.Print Err.Description
    
Resume ExitPoint
End Function

'converts selected msoControlType enumerations to values
Function GetType(rg As Range) As Long
    
Dim sType As String
    
    sType 
= rg.Offset(0, TYPE_OFFSET).Value
    
    
Select Case sType
        
Case "msoControlPopup"
            
GetType = MsoControlType.msoControlPopup
        
Case "msoControlButton"
            
GetType = MsoControlType.msoControlButton
        
Case "msoControlDropdown"
            
GetType = MsoControlType.msoControlDropdown
        
Case Else
            
GetType = MsoControlType.msoControlPopup
    
End Select
End Function

Sub DeleteMyMenu2()
    DeleteMenu 
"MyMenu2"
End Sub

Sub DeleteMyMenu3()
    DeleteMenu 
"MyMenu3"
End Sub

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