细品RibbonX(45):在快速访问工具栏(QAT)中添加项目
资料整理来自于论坛
完整版下载地址:http://download.csdn.net/download/nodeman/10264659
Loading ...
快速访问工具栏(QAT)是Office 2007新用户界面的一部分,可以使用老的Office工具栏定制方法进行定制。下面,我们主要介绍如何使用XML定制QAT。
概述
QAT可以包含共享控件和特定文档控件,也可以包含整个控件组(内置的和自定义的)以方便地在单一位置存储多个控件。
要定制QAT,必须从头开始设计用户界面,这意味着必须将startFromScratch属性设置为true:
<ribbonstartFromScratch="true">
在处理QAT时,你会注意到有两类图标,一种在其周围有边框而另一种则没有,这种区别表明哪种控件是共享控件,哪种控件是文档控件。
QAT文档控件的XML代码如下:
<qat>
<documentControls>
<control/>
</documentControls>
</qat>
QAT共享控件的XML代码如下:
<qat>
<sharedControls>
<control/>
</sharedControls>
</qat>
在QAT中添加自定义和内置命令
快速访问工具栏共享或文档控件的子元素如下表。
表:QAT的子元素
对象 | 用来做什么 |
control | 引用可以表现其它对象例如按钮、拆分按钮、组等的普通控件对象 |
button | 引用按钮控件 |
separator | 引用分隔条控件 |
如下图所示,在QAT中添加内置控件和自定义按钮。
XML代码如下:
<qat>
<documentControls>
<control
idMso="Bold"
screentip="Make it Bold"
supertip="Click here to make the selected text bold."/>
<button
id="rxbtnOpen"
imageMso="FileOpen"
screentip="This is Happy"
supertip="Click here for a happy message"
onAction="rxbtnOpen_click"/>
</documentControls>
</qat>
可以使用control对象引用内置的按钮(本例中为加粗按钮),接着使用按钮创建自已的定制按钮(可以使用control对象引用其它控件例如按钮或拆分按钮)。
下面的示例创建一个splitButton控件,然后将其添加到QAT。因为QAT没有splitButton子元素,我们必须在QAT之外创建splitButton,然后将其引用到QAT。可以通过以普通的方式添加splitButton来实现——也就是说,通过将其添加到组中开始:
<group
id="rxgrp"
label="My Custom Group">
<splitButton
id="rxsbtn"
size="large">
<button
id="rxbtn2"
imageMso="HappyFace"
label="My Happy Split"/>
<menu
id="rxmnu">
<button
id="rxbtn3"
label="My Happy Menu"
imageMso="HappyFace"
onAction="rxbtn3_click"/>
</menu>
</splitButton>
</group>
上面已经有splitButton并带有一个菜单,菜单中包含一个按钮。由于QAT使用现有的控件,因此现在可以在QAT中引用已存在的拆分按钮了,XML代码如下:
<qat>
<documentControls>
<control
id="rxsbtn"
imageMso="HappyFace"
screentip="This is Happy"
supertip="Click here for a happy message"/>
</documentControls>
</qat>
结果如下图所示。
在QAT中添加自定义和内置组
必须首先创建组,然后从QAT中引用指定该组的id。可以添加组到选项卡中并使其在选项卡中不可见而在QAT中可见。
如上图所示,My QAT Custom Group属于自定义的“Home”选项卡,然而我们将其可见属性设置为False,使其在选项卡上隐藏而在QAT中可见。XML代码如下:
<customUIxmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbonstartFromScratch="true">
<tabs>
<tab
id="rxtabHome"
label="Home">
<group
idMso="GroupClipboard"/>
<group
idMso="GroupFont"/>
<group
idMso="GroupAlignmentExcel"/>
<group
idMso="GroupNumber"/>
<group
idMso="GroupStyles"/>
<group
idMso="GroupCells"/>
<group
idMso="GroupEditingExcel"/>
<group
id="rxgrp"
label="My QAT Custom Group"
getVisible="rxshared_getVisible">
<button
id="rxbtnHappy"
label="Mr. Happy Face"
imageMso="HappyFace"
size="large"
onAction="rxshared_click"/>
<button
id="rxbtnHappy2"
label="Mr. Happy Face 2"
imageMso="HappyFace"
size="large"
onAction="rxshared_click"/>
</group>
</tab>
</tabs>
<qat>
<documentControls>
<control
idMso="GroupInsertChartsExcel"/>
<control
idMso="GroupFunctionLibrary"/>
<control
id="rxgrp"
imageMso="FormatCellsDialog"/>
</documentControls>
</qat>
</ribbon>
</customUI>
这里,因为要处理QAT,所以我们从头开始定制用户界面,然后以常规方式设置自定义选项卡和组并在自定义组中添加了两个按钮,将自定义组的getVisible属性设置为False,使其不会在选项卡中显示。最后,在QAT标签中,添加了两个自定义组,然后使用通用的control对象来引用想在QAT中显示的自定义组,同时为组赋予了内置的图像。
注意,有时虽然我们在QAT中定制了组,但打开Excel时不会出现,这是QAT中的一个“小问题”,后文将给出解决方法。
重利用QAT控件
当重利用QAT中的控件时,实际上重利用与之相关的命令,然后作为控件在QAT中添加相同的命令。
重利用的一个主要优势是会对该控件产生全局影响。
下面的XML代码重利用Excel中的两个控件——打开和保存:
<customUIxmlns="http://schemas.microsoft.com/office/2006/01/customui"
onLoad="rxIRibbonUI_onLoad">
<commands>
<command
idMso="FileSave"
onAction="rxFileSave_repurpose"/>
<command
idMso="FileOpen"
onAction="rxFileOpen_repurpose"/>
</commands>
<ribbonstartFromScratch="true">
<qat>
<documentControls>
<control
idMso="FileSave"
screentip="Repurposed Save"
supertip="This is a repurposed command"/>
<control
idMso="FileOpen"
screentip="Repurposed File Open"
supertip="This is a repurposed command"/>
</documentControls>
</qat>
</ribbon>
</customUI>
首先,声明希望重利用的命令并赋宏给每个控件,接着在ribbon标记里定义希望在QAT中出现的命令。
注意,这将产生全局影响,也就是说,如果在该命令出现的任一位置单击该命令或者使用指向该命令的快捷键(这里是Ctrl+o和Ctrl+s),该命令将指向赋值给onAction属性的回调。
在Excel中还可以使用不同的方式。Excel有一个名为OnKey的便捷的方法,当按下指定的键或键组合时触发。这是一个应用程序级的方法,因此一旦在某工作簿中禁用了某命令,所有在相同会话中打开的其它工作簿都将禁用该命令。
因此,在Excel中,如果仅仅需要取消包含UI的工作簿中的快捷键,那么在移动到另一个工作簿中时或者当打开工作簿时需要撤销该快捷键的取消。因为这是一个应用程序级的事件,所以需要使用类模块来监控并响应在工作簿间的转换。
在Excel项目中添加一个类模块并命名,本例中命名为clsAppExcelEvents,输入下面的代码:
Public WithEvents appXL As Excel.Application
Private Sub ShortcutsEnabled(ByVal blnEnabled As Boolean)
Select Case blnEnabled
Case Is = True
Application.OnKey "^o"
Application.OnKey "^s"
Case Is = False
Application.OnKey "^o", "commandDisabled"
Application.OnKey "^s", "commandDisabled"
End Select
End Sub
Private Sub setEnabled(ByVal Wb As Workbook)
Select Case Wb.Name
Case Is = ThisWorkbook.Name
ShortcutsEnabled False
Case Else
ShortcutsEnabled True
End Select
End Sub
注意,在类模块的声明部分声明Excel应用程序。有两个程序来实现这项任务:一个程序检查哪个工作簿是活动工作簿,另一个程序指定OnKey方法。OnKey方法的键组合字符之后,是程序名commandDisabled,该程序必须放置在标准模块中。
在类模块中,可以指定监控的事件。例如,可以监控某工作簿的激活或失活,决定是否取消快捷键:
Private Sub appXL_WorkbookActivate(ByVal Wb As Workbook)
setEnabled Wb
End Sub
Private Sub appXL_WorkbookDeactivate(ByVal Wb As Workbook)
setEnabled Wb
End Sub
最后,需要在工程打开时设置类,这由包含该工程的工作簿的Open事件来实现:
Dim XL As New clsAppExcelEvents
Private Sub Workbook_Open()
Set XL.appXL = Application
End Sub
使用表驱动(Table-Driven)方式定制QAT
下图是一个自定义QAT的示例,使用表装载详细信息到QAT中。
首先,编写包含UI和QAT菜单按钮的XML代码,这里创建的是文档控件按钮:
<documentControls>
<control
id="rxgrp"
imageMso="AdvancedFileProperties"/>
<button
id="rxbtnShowPopup"
image="rob"
screentip="This is Robert's QAT"
supertip="You can only customize the QAT by starting from scratch. If you do not do that you will not be able to make any changes..."
onAction="rxbtnShowPopup_Click"
/>
</documentControls>
上述XML代码将产生上图所示的两个QAT按钮,这里的关键是赋给onAction属性的回调,单击该按钮后将显示菜单。
接着,创建包含菜单信息的表,如下图所示。
上图所示的表只是一个建议,因为您可以在其中添加更多的选项。现在,使用VBA阅读该表并创建菜单:
Public Const POPNAME As String = "MY POPUP"
Sub loadPopup()
Dim mnuWs As Worksheet
Dim cmdbar As CommandBar
Dim cmdbarPopup As CommandBarPopup
Dim cmdbarBtn As CommandBarButton
Dim nRowCount As Long
Call unloadPopup
Set mnuWs = ThisWorkbook.Sheets("MenuItems")
Set cmdbar = Application.CommandBars.Add(POPNAME, msoBarPopup)
nRowCount = 2
With mnuWs
Do Until IsEmpty(.Cells(nRowCount, 1))
Select Case UCase(.Cells(nRowCount, 1))
Case "POPUP"
Set cmdbarPopup = cmdbar.Controls.Add(msoControlPopup)
cmdbarPopup.Caption = .Cells(nRowCount, 2)
If .Cells(nRowCount, 3) <> "" Then
cmdbarPopup.BeginGroup = True
End If
Case "BUTTON"
Set cmdbarBtn = cmdbarPopup.Controls.Add(msoControlButton)
cmdbarBtn.Caption = .Cells(nRowCount, 2)
If .Cells(nRowCount, 3) <> "" Then
cmdbarBtn.BeginGroup = True
End If
cmdbarBtn.FaceId = .Cells(nRowCount, 4)
cmdbarBtn.OnAction = .Cells(nRowCount, 5)
Case "BUTTON_STANDALONE"
Set cmdbarBtn = cmdbar.Controls.Add(msoControlButton)
cmdbarBtn.Caption = .Cells(nRowCount, 2)
If .Cells(nRowCount, 3) <> "" Then
cmdbarBtn.BeginGroup = True
End If
cmdbarBtn.FaceId = .Cells(nRowCount, 4)
cmdbarBtn.OnAction = .Cells(nRowCount, 5)
End Select
nRowCount = nRowCount + 1
Loop
End With
End Sub
Sub unloadPopup()
On Error Resume Next
Application.CommandBars(POPNAME).Delete
End Sub
Sub showAbout()
MsgBox "This is a sample on how to customize the QAT on the fly!!", vbInformation
End Sub
Sub showHelp()
On Error GoTo Err_Handler
ThisWorkbook.FollowHyperlink "http://www.msofficegurus.com", , True, True
Exit Sub
Err_Handler:
MsgBox Err.Description, vbCritical, Err.Number
End Sub
最后,需要编写回调的代码。使用onLoad事件调用loadPopup过程,以便创建弹出菜单,并准备当在QAT中单击该按钮时使用,也包含当发生单击时显示弹出菜单的单击事件代码:
Dim grxIRibbonUI As IRibbonUI
Sub rxIRibbonUI_onLoad(ribbon As IRibbonUI)
On Error Resume Next
Set grxIRibbonUI = ribbon
Application.Workbooks.Add
If ActiveWorkbook.Name <> ThisWorkbook.Name Then
With ActiveWorkbook
.Saved = True
.Close
End With
End If
' 可以在这个事件或者ThisWorkbook的Open事件中装载弹出菜单
Call loadPopup
End Sub
Sub rxbtnShowPopup_Click(control As IRibbonControl)
On Error Resume Next
Application.CommandBars(POPNAME).ShowPopup
End Sub
Sub rxbtnHappy_Click(control As IRibbonControl)
MsgBox "This is Mr. Happy Face... hurray!!", vbExclamation
End Sub
定制QAT时的一些注意事项
虽然在QAT中可以方便地实现自定义,但也有一些缺陷。
(1)无法装载控件
上文中曾经谈到,在定制好后,例如按钮和组,打开工作簿时,却发现定制的控件没有出现。这种情况在使用sharedControls时非常普遍。
一种解决方法是先最小化工作簿,然后再最大化,通过刷新来使定制的控件出现;或者再打开一个工作簿后,将其关闭,看看定制的控件是否出现。
(2)无法为控件装载自定义图像
共享控件的表现通常无法预料,并且不能提供可信赖且一致的界面,因此建议在共享控件中尽量不要使用自定义图像。
至于文档控件,可以使用下面的过程刷新包含UI的窗口来解决此类问题:
Sub rxIRibbonUI_onLoad(ribbon As IRibbonUI)
Set grxIRibbonUI = ribbon
On Error Resume Next
Application.Workbooks.Add
If ActiveWorkbook.Name <> ThisWorkbook.Name Then
With ActiveWorkbook
.Saved = True
.Close
End With
End If
End Sub
上述技巧也能用于无法装载自定义控件中。
(3)复制控件
在QAT中控件的复制通常发生在工作簿或文档之间切换时。假设有一个包含定制的QAT的工作簿,当按Alt+Tab移动到另一个文档,然后返回定制的工作簿时,在QAT中的控件被复制、三次复制、四次复制……这种复制能够被传播到没有包含任何XML定制的其它工作簿和文档。
此时,需要关闭后重新打开文档才能消除这种不应有的复制。