The Microsoft Office Backstage view, new to Office 2010, replaces the traditional File menu to provide a centralized space for file management tasks such as opening new or existing files, defining document properties, and sharing information. Like the Microsoft Office Fluent ribbon, the Backstage view is fully extensible by using XML to define the structure, components, and callback procedures to give those components functionality.
In certain instances you may want to hide or display Backstage view controls based on actions the customer takes from other controls in the Backstage view. This article illustrates techniques for dynamically changing the visibility of a Backstage view group control and dynamically changing the visibility of individual controls based on customer actions.
This article uses Trang Luu's Custom UI Editor to simplify adding custom user interface (UI) XML to the Microsoft Excel 2010 workbook. You must download and install the Custom UI Editor to follow the steps provided in this article.
This article customizes the Backstage view for a Microsoft Excel 2010 workbook by using a combination of XML and Microsoft Visual Basic for Applications (VBA) code. The XML defines a custom tab and the controls to display in the Backstage view. The VBA code provides the functionality required by the callback procedures defined in the custom UI XML. It also walks you through the following steps to show how to create a customized Backstage view in an Excel 2010 workbook:
Create a sample Excel workbook with a Backstage view.
Add the custom UI XML.
Add the VBA callback code.
View the custom Backstage view page.
Creating the Sample Excel Workbook
In this Visual How To, you add custom UI XML and VBA code to an Excel 2010 workbook.
Note
You must create the Excel workbook as a macro-enabled workbook (.xlsm) to support the VBA code.
To create the workbook
Start Microsoft Excel 2010.
On the File menu, click Save As.
In the Save As dialog box, in the Save as type drop-down list, select Excel macro-enabled workbook (*.xlsm).
Save the document as C:\Temp\BackstageViewDynamicVisibility.xlsm.
Adding the Custom UI XML
The Custom UI Editor simplifies adding custom UI XML to the workbook that you created in the previous step.
To add the custom UI XML
Adding the VBA Callback Code
The VBA callback procedures add functionality to the custom Backstage view components that you added by using custom UI XML in the previous procedure.
To add the VBA callback code
Start Microsoft Excel 2010.
On the File tab, click Open.
Open the C:\Temp\BackstageViewDynamicVisibility.xlsm workbook.
Select the Developer tab.
Click Visual Basic.
On the Insert menu, click Module.
Select Module1 and copy the following VBA code into the file.
'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
On the File menu, click Save.
Close the Visual Basic for Applications Editor and return to the workbook.
View the Custom Backstage View Page
To view the custom Backstage view page defined above, display the Backstage view by selecting the File tab. This is the new Backstage view. After the Backstage view is displayed, select the Dynamic Visibility tab, which is located on the built-in Info tab. When you select the Dynamic Visibility tab, the custom Backstage view page defined in the previous steps is displayed.
Figure 1. Custom Backstage view page
Extending the Office 2010 Backstage view to include custom pages and controls requires a combination of adding custom UI XML to the Office document and adding VBA code to provide functionality for the callbacks specified in the custom UI XML.
The sample code shows how to dynamically change the visibility of a Backstage view group control or the visibility of individual controls based on actions taken using other controls in the Backstage view.
Initialize the Custom UI
In some cases, a callback procedure makes a change that requires redisplaying Backstage view controls. To redisplay Backstage view controls, call the Invalidate method or the InvalidateControl method of the RibbonUI object.
The following code example shows how to store a reference to the RibbonUI control when the custom UI is loaded. The customUI element contains the onLoad attribute. In this instance, the attribute specifies the OnLoad callback. The OnLoad callback stores a reference to the RibbonUI object. The RibbonUI object is used in callbacks to redisplay the Backstage view controls. The onLoad callback also initializes variables used in the code.
<!-- 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
Dynamically Change the Visibility of a Group Control
Sometimes you may want to display a Backstage view group control that is based on actions taken by the user using other controls. This article discusses switching between displaying the Engineering Group group or the Marketing Group group based on the selection made in the Groups menu of the Specification Detail.
The following custom UI XML examples show how to specify the callbacks to dynamically switch the display between the two groups. The Groups button specifies an onAction callback that switches between the Engineering Group controls and Marketing Group controls. The Marketing Group control and Engineering Group control specify the getVisibility callbacks. These callbacks determine whether the group should be displayed or hidden.
<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>
The following code example shows how the onAction callback of the Groups menu in the Specification Detail, SwitchGroups, switches between displaying the Engineering Group control or the Marketing Group control. The SwitchGroups callback reverses the Boolean values of the engineeringGroupVisible variable and marketingGroupVisible variable that determine whether the group control should be displayed. After the variables are changed, the Invalidate method of the RibbonUI object is called to redisplay the Backstage view controls. When the Invalidate method is called, the getVisible callbacks for the Engineering Group control and Marketing Group control are re-executed causing a switch in which group displayed.
'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
The following code example shows how the GetVisible callback and the GetEngineeringGroupVisibility callback of the Engineering Group control, and the getVisible callback and the GetMarketingGroupVisibilty callback of the Marketing Group control, control the display of the groups. Both callbacks work by returning the Boolean value of the variable that tracks if the group should be visible.
'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
Dynamically Change the Visibility of Individual Controls
There may be instances where you want to display individual Backstage view controls that are based on actions taken by the user using other controls. This article displays an initial set of tasks for defining work scope. After these initial tasks are marked as complete, a second set of tasks are displayed for calculating costs. After all tasks are marked as complete, an image and label identifying that all tasks are completed are displayed.
The following custom UI XML example shows how to specify the callbacks to dynamically display individual controls that are based on user actions in other controls. The getVisible callback of the Calculate Costs task of the category is specified to only display these tasks after the category control tasks of the Define Work Scope are marked as completed. The task complete image and task complete label controls set their getVisible callback to only display the controls after all tasks are completed. Each task control sets its onAction callback to mark the task as complete.
<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>
The following code example shows how the getVisible callback and the GetCalculateCostsVisibility callback of the Calculate Costs task category control, control the display of the Calculate Costs category. Initially no tasks are completed and the GetCalculateCostsVisibility method returns False to hide the category control of the Calculate Costs task. When all tasks in the Define Work Scope category are completed, the GetCalculateCostsVisibility method returns True to display the Calculate Costs task category.
'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
The following code example shows how the getVisible callback of the imageControl control and labelControl control, the GetTasksCompleteVisibility method, hides the tasks complete controls until all tasks are marked as completed. Initially no tasks are completed and the GetTasksCompleteVisibility method returns False to hide the tasks complete controls. After all tasks in both the Define Work Scope category and Calculate Costs category are marked as complete the GetTasksCompleteVisibility method returns True to display the tasks complete controls.
'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
The following code fragment shows how the onAction callback of the task control, SetTaskComplete, marks tasks as completed. The SetTaskComplete callback identifies which task was clicked and sets the appropriate task complete variable to True. After the task is marked as complete, the InvalidateControl method of the RibbonUI object is called to limit the redisplay and re-execution of callbacks to only those Backstage view controls affected by the change. Tasks in the Define Work Scope category can only affect the display of the Calculate Costs category control so the control identifier for the category control for the Calculate Costs control, calculateCostsCategory, is passed to the InvalidateControl method when these tasks are marked as completed. Tasks in the Calculate Costs category can only affect the display of the task complete imageControl object and labelControl object so the InvalidateControl method is called for each control when the tasks are marked as completed.
'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
|