Microsoft Office Backstage 视图是 Office 2010 中的一项新功能,它取代了传统的"文件"菜单,可用于集中处理文件管理任务,如打开新的或现有的文件、定义文档属性以及共享信息。与 Microsoft Office Fluent 功能区一样,Backstage 视图也可以完全扩展,通过使用 XML 定义结构、组件和回调过程来为这些组件提供功能。
在某些情况下,您可能需要根据客户对 Backstage 视图中的其他控件执行的操作来隐藏或显示 Backstage 视图控件。本文将演示动态更改 Backstage 视图 group 控件的可视性的方法,以及基于客户操作动态更改单个控件的可视性的方法。
本文使用 Trang Luu 的自定义 UI 编辑器(该链接可能指向英文页面)简化了将自定义用户界面 (UI) XML 添加到 Microsoft Excel 2010 工作簿的过程。您必须下载并安装自定义 UI 编辑器才能按照本文中提供的步骤进行操作。
本文通过使用 XML 和 Microsoft Visual Basic for Applications (VBA) 代码的组合来自定义 Microsoft Excel 2010 工作簿的 Backstage 视图。XML 定义要在 Backstage 视图中显示的自定义选项卡和控件。VBA 代码提供了自定义 UI XML 中定义的回调过程所需的功能。本文还指导您完成下列步骤以说明如何在 Excel 2010 工作簿中创建自定义 Backstage 视图:
使用 Backstage 视图创建示例 Excel 工作簿。
添加自定义 UI XML。
添加 VBA 回调代码。
查看自定义 Backstage 视图页。
创建示例 Excel 工作簿
在此直观操作方法中,您将向 Excel 2010 工作簿中添加自定义的 UI XML 和 VBA 代码。
> [!NOTE]
> 您必须将 Excel 工作簿创建为启用宏的工作簿 (.xlsm) 才能支持 VBA 代码。
启动 Microsoft Excel 2010。
在"文件"菜单上,单击"另存为"。
在"另存为"对话框的"保存类型"下拉列表中,选择"Excel 启用宏的工作簿(*.xlsm)"。
将文档另存为 C:\Temp\BackstageViewDynamicVisibility.xlsm。
添加自定义 UI XML
自定义 UI 编辑器简化了将自定义 UI XML 添加到您在上一步骤中创建的工作簿的过程。
添加 VBA 回调代码
VBA 回调过程将向您在前一过程中使用自定义 UI XML 添加的自定义 Backstage 视图组件添加功能。
启动 Microsoft Excel 2010。
在"文件"选项卡上,单击"打开"。
打开 C:\Temp\BackstageViewDynamicVisibility.xlsm 工作簿。
选择"开发工具"选项卡。
单击"Visual Basic"。
在"插入"菜单上,单击"模块"。
选择"Module1",然后将下面的 VBA 代码复制到文件中。
'Reference to the ribbon for refreshing the UI.
Public processRibbon As IRibbonUI
'Variables that track the group that is displayed.
Public engineeringGroupVisible As Boolean
Public marketingGroupVisible As Boolean
'Variables that track the completed tasks.
Public taskOneComplete As Boolean
Public taskTwoComplete As Boolean
Public taskThreeComplete As Boolean
Public taskFourComplete As Boolean
'Callback for customUI.onLoad.
Sub onLoad(ribbon As IRibbonUI)
'Store a reference to the ribbon for refreshing the UI.
Set processRibbon = ribbon
'Initialize to display the Engineering Group first.
engineeringGroupVisible = True
End Sub
'Visibility for the Engineering Group group control.
Sub GetEngineeringGroupVisibility(control As IRibbonControl, _
ByRef returnedVal)
returnedVal = engineeringGroupVisible
End Sub
'Visibility for the Marketing Group group control.
Sub GetMarketingGroupVisibility(control As IRibbonControl, _
ByRef returnedVal)
returnedVal = marketingGroupVisible
End Sub
'Called when the Switch Groups button is clicked.
'The variables tracking the visible group are swapped
' to switch the display between the two groups.
Sub SwitchGroups(control As IRibbonControl)
engineeringGroupVisible = Not engineeringGroupVisible
marketingGroupVisible = Not engineeringGroupVisible
'Invalidate resets the UI. This causes all controls
' to redisplay and execute all relevant callbacks.
processRibbon.Invalidate
End Sub
'Label to display for the Switch Groups button.
'Text returned is based on the current group that is displayed.
Sub GetSwitchGroupsLabel(control As IRibbonControl, ByRef returnedVal)
If (engineeringGroupVisible) Then
returnedVal = "Switch to Marketing Group"
Else
returnedVal = "Switch to Engineering Group"
End If
End Sub
'Returns the text to display for each Specification Detail editBox.
Sub GetSpecDetailText(control As IRibbonControl, ByRef returnedVal)
Select Case control.ID
Case "specTitle"
returnedVal = "Flexible Bracket"
Case "specDesigner"
returnedVal = "Andrew Fuller"
Case "specEngineer"
returnedVal = "Nancy Davolio"
Case "specTeam"
returnedVal = "Design"
Case "specCost"
returnedVal = "$896,210"
End Select
End Sub
'Returns the text to display for each Marketing editbox.
Sub GetMarketingDetail(control As IRibbonControl, ByRef returnedVal)
Select Case control.ID
Case "marketingManager"
returnedVal = "Janet Leverling"
Case "marketingBudget"
returnedVal = "$144,078"
Case "marketingEndDate"
returnedVal = Date + 20
End Select
End Sub
'Returns the text to display for each Engineering editbox.
Sub GetEngineeringDetail(control As IRibbonControl, ByRef returnedVal)
Select Case control.ID
Case "engineeringManager"
returnedVal = "Robert Jones"
Case "engineeringBudget"
returnedVal = "$197,955"
Case "engineeringEndDate"
returnedVal = Date + 10
End Select
End Sub
'Visibility for the second task category.
'The second task category does not display until tasks in the
' first task category are marked complete.
Sub GetCalculateCostsVisibility(control As IRibbonControl, _
ByRef returnedVal)
If (taskOneComplete And taskTwoComplete) Then
returnedVal = True
Else
returnedVal = False
End If
End Sub
'Visibility for the task complete controls.
'The task complete controls do not display until all tasks
' are marked complete.
Sub GetTasksCompleteVisibility(control As IRibbonControl, _
ByRef returnedVal)
If (taskOneComplete And taskTwoComplete _
And taskThreeComplete And taskFourComplete) Then
returnedVal = True
Else
returnedVal = False
End If
End Sub
'Called when a task is clicked.
'Marks the task as complete and then calls the InvalidateControl method to
' redisplay only the controls impacted by the change in status.
Sub SetTaskComplete(control As IRibbonControl)
Select Case control.ID
Case "defineScope"
taskOneComplete = True
'Redisplay the second category control
processRibbon.InvalidateControl("calculateCostsCategory")
Case "assignTasks"
taskTwoComplete = True
'Redisplay the second category control
processRibbon.InvalidateControl("calculateCostsCategory")
Case "calcManHours"
taskThreeComplete = True
'Redisplay the task complete controls
processRibbon.InvalidateControl("tasksCompleteImage")
processRibbon.InvalidateControl("tasksCompleteLabel")
Case "calcOverheadCosts"
taskFourComplete = True
'Redisplay the task complete controls
processRibbon.InvalidateControl("tasksCompleteImage")
processRibbon.InvalidateControl("tasksCompleteLabel")
End Select
End Sub
在"文件"菜单上,单击"保存"。
关闭 Visual Basic for Applications 编辑器,并返回到工作簿。
查看自定义 Backstage 视图页
若要查看先前定义的自定义 Backstage 视图页,可选择"文件"选项卡来显示 Backstage 视图。此时将显示新建的 Backstage 视图。显示 Backstage 视图之后,选择位于内置的"信息"选项卡上的"动态可视性"选项卡。选择"动态可视性"选项卡时,将可显示在前面的步骤中定义的自定义 Backstage 视图页。
图 1. 自定义 Backstage 视图页
若要扩展 Office 2010 Backstage 视图以包含自定义页和控件,则需要将自定义 UI XML 添加到 Office 文档,并添加 VBA 代码以提供自定义 UI XML 中指定的回调的功能。
该示例代码将演示如何动态更改 Backstage 视图 group 控件的可视性或基于使用 Backstage 视图中的其他控件采取的操作的单个控件的可视性。
初始化自定义 UI
在某些情况下,回调过程会执行需要重新显示 Backstage 视图控件的更改操作。若要重新显示 Backstage 视图控件,可调用 RibbonUI 对象的 Invalidate 方法或 InvalidateControl 方法。
下面的代码示例演示如何在加载自定义 UI 时存储对 RibbonUI 控件的引用。customUI 元素包含 onLoad 属性。在此实例中,该属性用于指定 OnLoad 回调。OnLoad 回调将存储对 RibbonUI 对象的引用。RibbonUI 对象在回调中用来重新显示 Backstage 视图 控件。onLoad 回调还用于初始化代码中使用的变量。
<!-- customUI is the root tag of all Fluent UI customizations. -->
<customUI xmlns="https://schemas.microsoft.com/office/2009/07/customui"
onLoad="OnLoad">
'Reference to the ribbon for refreshing the UI.
Public processRibbon As IRibbonUI
'Variables that track the group that is displayed.
Public engineeringGroupVisible As Boolean
Public marketingGroupVisible As Boolean
'Variables that track the completed tasks.
Public taskOneComplete As Boolean
Public taskTwoComplete As Boolean
Public taskThreeComplete As Boolean
Public taskFourComplete As Boolean
'Callback for customUI.onLoad.
Sub onLoad(ribbon As IRibbonUI)
'Store a reference to the ribbon for refreshing the UI.
Set processRibbon = ribbon
'Initialize to display the Engineering Group first.
engineeringGroupVisible = True
End Sub
动态更改 group 控件的可视性
有时,您可能需要显示一个 Backstage 视图 group 控件,该控件将基于用户使用其他控件执行的操作。本文将讨论如何通过在"Specification Detail"的"Groups"菜单中所做的选择来切换"Engineering Group"或"Marketing Group"的显示。
以下自定义 UI XML 示例将演示如何指定回调来动态切换两个组的显示。"Groups"按钮用于指定切换"Engineering Group"控件和"Marketing Group"控件的 onAction 回调。"Marketing Group"控件和"Engineering Group"控件用于指定 getVisibility 回调。这些回调将确定相关组是应显示还是隐藏。
<primaryItem>
<menu id="switchMenu" label="Groups"
imageMso="ControlLayoutStacked" >
<menuGroup id="menuGroup">
<!-- The onAction callback switches between
displaying the Marketing Group or the Engineering
Group below. -->
<button id="switchGroups"
getLabel="GetSwitchGroupsLabel"
onAction="SwitchGroups"/>
</menuGroup>
</menu>
</primaryItem>
...
<!-- The getVisible callback determines if the
Marketing Group should display based on the current
switchGroups button selection. -->
<group id="marketingGroupDetails" label="Marketing Group"
getVisible="GetMarketingGroupVisibility">
...
</group>
<!-- The getVisible callback determines if the
Engineering Group should display based on the
current switchGroups button selection. -->
<group id="engineeringGroupDetails" label="Engineering Group"
getVisible="GetEngineeringGroupVisibility" >
...
</group>
以下代码示例将演示"Specification Detail"中的"Groups"菜单的 onAction 回调 (SwitchGroups) 如何切换"Engineering Group"控件或"Marketing Group"控件的显示。SwitchGroups 回调用于反转 engineeringGroupVisible 变量和 marketingGroupVisible 变量的布尔值,这些布尔值将确定是否应显示 group 控件。在这些变量更改之后,将调用 RibbonUI 对象的 Invalidate 方法来重新显示 Backstage 视图 控件。在调用 Invalidate 方法后,将重新执行对"Engineering Group"控件和"Marketing Group"控件的 getVisible 回调,从而切换组的显示。
'Called when the Switch Groups button is clicked.
'The variables tracking which group is visible are swapped
' to switch the display between the two groups.
Sub SwitchGroups(control As IRibbonControl)
engineeringGroupVisible = Not engineeringGroupVisible
marketingGroupVisible = Not engineeringGroupVisible
'The Invalidate method resets the UI causing all controls
' to redisplay and executing all relevant callbacks.
processRibbon.Invalidate
End Sub
以下代码将演示"Engineering Group"控件的 GetVisible 回调和 GetEngineeringGroupVisibility 回调以及"Marketing Group"控件的 getVisible 和 GetMarketingGroupVisibilty 回调如何控制这两个组的显示。这两个组的回调是通过返回用于跟踪组是否应显示的变量的布尔值来工作的。
'Visibility for the Engineering Group control.
Sub GetEngineeringGroupVisibility(control As IRibbonControl, _
ByRef returnedVal)
returnedVal = engineeringGroupVisible
End Sub
'Visibility for the Marketing Group control.
Sub GetMarketingGroupVisibility(control As IRibbonControl, _
ByRef returnedVal)
returnedVal = marketingGroupVisible
End Sub
动态更改单个控件的可视性
在某些情况下,您可能需要显示基于用户使用其他控件执行的操作的单个 Backstage 视图 控件。本文将介绍一组用于定义工作范围的初始任务。在这些初始任务标记为完成后,将显示用于计算成本的第二组任务。在所有任务都标记为完成后,将显示用于标明所有任务都已完成的图像和标签。
以下自定义的 UI XML 示例将演示如何通过指定回调来动态显示基于用户使用其他控件执行的操作的单个控件。category 的"Calculate Costs"任务的 getVisible 回调指定为只能在"Define Work Scope"的 category 控件任务标记为完成后才能显示这些任务。任务完成图像和任务完成标签控件将各自的 getVisible 回调设置为只能在所有任务完成后显示相关的控件。每个 task 控件都将其 onAction 回调设置为将任务标记为完成。
<taskGroup id="bidProcessTaskGroup"
label="Contract Bid Process Checklist" >
<!-- The first task category always displays -->
<!-- The onAction callback marks tasks as
completed when the task is clicked. -->
<category id="defineWorkScopeCategory"
label="Define work and tasks - Complete tasks in order.">
<task id="defineScope" label="Define the Scope of Work."
imageMso="_1" onAction="SetTaskComplete"/>
<task id="assignTasks" label="Assign the Tasks"
imageMso="_2" onAction="SetTaskComplete"/>
</category>
<!-- The getVisible callback only displays the
second task category after the tasks in the first
category are complete. -->
<!-- The onAction callback marks tasks as
complete when the task is clicked -->
<category id="calculateCostsCategory"
label="Calculate costs - Complete tasks in order."
getVisible="GetCalculateCostsVisibility" >
<task id="calcManHours" label="Calculate Total Man-Hours"
imageMso="_3" onAction="SetTaskComplete"/>
<task id="calcOverheadCosts" label="Determine Overhead Costs"
imageMso="_4" onAction="SetTaskComplete"/>
</category>
</taskGroup>
<group id="tasksCompleteGroup" >
<topItems>
<layoutContainer id="tasksCompleteLayout"
layoutChildren="horizontal" >
<!-- The getVisible callback only displays
this set of individual controls after all tasks
are complete. -->
<imageControl id="tasksCompleteImage"
imageMso="AcceptInvitation"
getVisible="GetTasksCompleteVisibility"/>
<labelControl id="tasksCompleteLabel"
label="The proposal is ready for review."
getVisible="GetTasksCompleteVisibility" />
</layoutContainer>
</topItems>
</group> <!-- The getStyle callback and getHelperText callback
dynamically set the Open Design Issues Group style
and text based on if there are any open issues. -->
<group id="openDesignIssuesGroup" label="Open Design Issues"
getStyle="GetIssuesStyle"
getHelperText="GetIssuesHelperText">
<topItems>
<!-- The layoutChildren attribute lays out
each set of issues controls horizontally. -->
<!-- The onAction callback marks issues as resolved
when the "Click to Resolve" button is clicked. -->
<!-- The getVisible callback hides the
issues after they are marked as resolved. -->
<layoutContainer id="delayIssueContainer"
layoutChildren="horizontal">
<button id="resolveDelayIssue" label="Click to Resolve"
imageMso="AcceptInvitation" onAction="ResolveIssue"
getVisible="getIssueVisibility" />
<labelControl id="delayIssue"
label="Issue: Delay in Material Delivery"
getVisible="getIssueVisibility" />
</layoutContainer>
<layoutContainer id="equipmentIssueContainer"
layoutChildren="horizontal">
<button id="resolveEquipmentIssue" label="Click to Resolve"
imageMso="AcceptInvitation" onAction="ResolveIssue"
getVisible="getIssueVisibility" />
<labelControl id="equipmentIssue"
label="Issue: Equipment Down Time"
getVisible="getIssueVisibility" />
</layoutContainer>
<layoutContainer id="laborIssueContainer"
layoutChildren="horizontal">
<button id="resolveLaborIssue" label="Click to Resolve"
imageMso="AcceptInvitation" onAction="ResolveIssue"
getVisible="getIssueVisibility" />
<labelControl id="laborIssue"
label="Issue: Labor Dispute"
getVisible="getIssueVisibility" />
</layoutContainer>
</topItems>
</group>
以下代码示例将演示"Calculate Costs"任务 category 控件的 getVisible 回调和 GetCalculateCostsVisibility 回调如何控制"Calculate Costs"类别的显示。最初,在无任务完成时,GetCalculateCostsVisibility 方法将返回 False 以隐藏"Calculate Costs"任务的 category 控件。在"Define Work Scope"类别中的所有任务都完成后,GetCalculateCostsVisibility 方法将返回 True 以显示"Calculate Costs"任务类别。
'Visibility for the second task category.
'The second task category does not display until tasks in the
' first task category are marked as complete.
Sub GetCalculateCostsVisibility(control As IRibbonControl, _
ByRef returnedVal)
If (taskOneComplete And taskTwoComplete) Then
returnedVal = True
Else
returnedVal = False
End If
End Sub
以下代码示例将演示 imageControl 控件和 labelControl 控件的 getVisible 回调(GetTasksCompleteVisibility 方法)是如何在所有任务尚未完成前隐藏任务完成控件的。最初,在无任务完成时,GetTasksCompleteVisibility 方法将返回 False 以隐藏任务完成控件。在"Define Work Scope"类别和"Calculate Costs"类别中的所有任务都标记为完成后,GetTasksCompleteVisibility 方法将返回 True 以显示任务完成控件。
'Visibility for the task complete controls.
'The task complete controls do not display until all tasks '
' are marked as complete.
Sub GetTasksCompleteVisibility(control As IRibbonControl, _
ByRef returnedVal)
If (taskOneComplete And taskTwoComplete _
And taskThreeComplete And taskFourComplete) Then
returnedVal = True
Else
returnedVal = False
End If
End Sub
以下代码段将演示 task 控件的 onAction 回调 (SetTaskComplete) 如何将任务标记为完成。SetTaskComplete 回调用于识别已单击的任务,并将相应的任务完成变量设置为 True。任务标记为完成后,将调用 RibbonUI 对象的 InvalidateControl 方法限制只允许那些受更改影响的 Backstage 视图 控件重新显示和重新执行回调。"Define Work Scope"类别中的任务只能影响"Calculate Costs"类别控件,因此,这些任务标记为完成后,"Calculate Costs"控件的 category 控件的控件标识符 calculateCostsCategory 将传递到 InvalidateControl 方法。"Calculate Costs"类别中的任务只能影响任务完成 imageControl 对象和 labelControl 对象的显示,因此,在这些任务标记为完成后,将为每个控件调用 InvalidateControl 方法。
'Called when a task is clicked.
'Marks the task as complete and then calls the InvalidateControl method to
' redisplay only the controls impacted by the change in status.
Sub SetTaskComplete(control As IRibbonControl)
Select Case control.ID
Case "defineScope"
taskOneComplete = True
'Redisplay the second category control.
processRibbon.InvalidateControl ("calculateCostsCategory")
Case "assignTasks"
taskTwoComplete = True
'Redisplay the second category control.
processRibbon.InvalidateControl ("calculateCostsCategory")
Case "calcManHours"
taskThreeComplete = True
'Redisplay the task complete controls.
processRibbon.InvalidateControl ("tasksCompleteImage")
processRibbon.InvalidateControl ("tasksCompleteLabel")
Case "calcOverheadCosts"
taskFourComplete = True
'Redisplay the task complete controls.
processRibbon.InvalidateControl ("tasksCompleteImage")
processRibbon.InvalidateControl ("tasksCompleteLabel")
End Select
End Sub
'Called when a resolve issue button is clicked.
'Sets the button's corresponding issue as resolved.
Sub ResolveIssue(control As IRibbonControl)
Select Case control.ID
Case "resolveDelayIssue"
delayIssueResolved = True
Case "resolveEquipmentIssue"
equipmentIssueResolved = True
Case "resolveLaborIssue"
laborIssueResolved = True
End Select
'Invalidate method is called to reset the UI causing all controls
' to redisplay and executing all relevant callbacks.
processRibbon.Invalidate
End Sub
|