Customizing the Format of Controls in the Office 2010 Backstage View

Office Visual How To

Summary:   Learn to define the horizontal or vertical layout of controls and how controls display in the Microsoft Office 2010 Backstage View. (11 printed pages)

Applies to: Excel 2010 | Office 2010 | Open XML | PowerPoint 2010 | VBA | Visual Studio | Word 2010

Published:   April 2010

Provided by:   Michael Case, iSoftStone

Overview

The Microsoft Office Backstage view, new to Microsoft 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 components functionality.

This Office Visual How To article shows how to create a document-specific customized Backstage view with a custom control format. The Backstage view uses the layoutContainer control to specify whether a set of controls is displayed vertically or horizontally. The Backstage view also uses callback procedures to dynamically define how a group of controls displays.

The example in this Visual How To uses Trang Luu's Custom UI Editor tool to simplify adding custom UI XML to a Microsoft Excel 2010 workbook. You must download and install the Custom UI Editor to follow the steps provided in this article.

Code It

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 workbook.

Note

You must create the Excel workbook as a macro-enabled workbook (.xlsm) to support the VBA code.

To create the workbook

  1. Start Microsoft Excel 2010.

  2. On the File menu, click Save As.

  3. In the Save As dialog box, in the Save as type drop-down list, select Excel macro-enabled workbook (*.xlsm).

  4. Save the document as C:\Temp\BackstageViewFormatControls.xlsm. Click Save to finish.

Add 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

  1. Start the Custom UI Editor.

  2. On the File menu, click Open.

  3. Select the C:\Temp\BackstageViewFormatControls.xlsm file that you created in the previous procedure, and then click Open.

  4. On the Insert menu, click Office 2010 Custom UI Part. This creates a customUI14.xml file in the document.

  5. Select the customUI14.xml file and copy the following XML into the file.

    <?xml version="1.0" encoding="utf-8"?>
    <!-- CustomUI is the root tag of all Office Fluent UI customizations. -->
    <customUI xmlns="https://schemas.microsoft.com/office/2009/07/customui"
          onLoad="onLoad">
      <!-- The Backstage view defines custom structure of the Backstage UI. -->
      <backstage>
        <tab id="customFormatTab" label="Customized Control Format"
             insertAfterMso="TabInfo">
          <firstColumn>
            <group id="specDetailsGroup" label="Specification Details"
                   getHelperText="GetSpecDetailsHelperText">
              <topItems>
                <!-- The layoutChildren attribute places 
                      this set of controls vertically. -->
                <!-- The GetSpecDetailText callback returns 
                      a value to display for each editBox. -->
                <layoutContainer id="specDetails" layoutChildren="vertical">
                  <editBox id="specTitle" label="Title:        "
                           getText="GetSpecDetailText" />
                  <editBox id="specDesigner" label="Designer: "
                           getText="GetSpecDetailText" />
                  <editBox id="specEngineer" label="Engineer: "
                           getText="GetSpecDetailText" />
                  <editBox id="specTeam" label="Team:      "
                           getText="GetSpecDetailText"/>
                  <editBox id="specCost" label="Cost:        "
                           getText="GetSpecDetailText"/>
                </layoutContainer>
                <!-- The layoutChildren attribute places 
                      the buttons horizontally. -->
                <layoutContainer id="specButtons" layoutChildren="horizontal">
                  <button id="getCostBasis" 
                          label="Get Cost Basis Info"/>
                  <button id="getCostCodes" 
                          label="Get Cost Codes"/>
                  <button id="getTeamCodes" 
                          label="Get Team Codes"/>
                </layoutContainer>
              </topItems>
            </group>
          </firstColumn>
          <secondColumn>
            <!-- The getStyle and getHelperText callbacks dynamically 
                  set the Open Design Issues Group style 
                  and text based on whether there are any open issues. -->
            <group id="openDesignIssuesGroup" label="Open Design Issues"
                   getStyle="GetIssuesStyle" 
                   getHelperText="GetIssuesHelperText">
              <topItems>
                <!-- The layoutChildren attribute places 
                      each set of issues controls horizontally. -->
                <!-- The onAction callback marks issues as resolved 
                      when the user clicks the Click to resolve button. -->
                <!-- 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>
          </secondColumn>
        </tab>
      </backstage>
    </customUI>
  6. On the File menu, click Save.

  7. Close the Custom UI Editor.

Add 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

  1. Start Microsoft Excel 2010.

  2. On the File tab, click Open.

  3. Open the BackstageViewFormatControls.xlsm workbook.

  4. Select the Developer tab.

  5. Click Visual Basic.

  6. On the Insert menu, click Module.

  7. 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 open design issues.
    Public delayIssueResolved As Boolean
    Public equipmentIssueResolved As Boolean
    Public laborIssueResolved As Boolean
    
    ' Store a reference to the ribbon for refreshing the UI.
    Sub OnLoad(ribbon As IRibbonUI)
      Set processRibbon = ribbon
    End Sub
    
    ' Helper text for the specification details group.
    Sub GetSpecDetailsHelperText(control As IRibbonControl, _
                                 ByRef returnedVal)
      returnedVal = "Please be sure that the following information " & _
                    "is kept up to date. Many processes rely on " & _
                    "this information."
    End Sub
    
    ' Returns the text to display for each specification detail editBox object.
    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
    
    ' Group style for the open design issues group.
    ' If all issues are not resolved the error style
    ' emphasizes the group.
    Sub GetIssuesStyle(control As IRibbonControl, _
                       ByRef returnedVal)
      If (delayIssueResolved And equipmentIssueResolved _
          And laborIssueResolved) Then
        ' This enumeration was renamed after the Office 2010 beta release.
        ' For the beta, use the OutSpaceSlabStyle.OutSpaceSlabStyleNormal enumeration.
        returnedVal = BackstageGroupStyle.BackstageGroupStyleNormal
      Else
        ' This enumeration was renamed after the Office 2010 beta release.
        ' For the beta release, use the OutSpaceSlabStyle.OutSpaceSlabStyleError enumeration.
        returnedVal = BackstageGroupStyle.BackstageGroupStyleError
      End If
    End Sub
    
    ' Helper text for the open design issues group.
    ' Text returned is based on the status of all issues.
    Sub GetIssuesHelperText(control As IRibbonControl, _
                            ByRef returnedVal)
      If (delayIssueResolved And equipmentIssueResolved _
          And laborIssueResolved) Then
        returnedVal = "All issues are resolved."
      Else
        returnedVal = "Click Resolve as issues are resolved."
      End If
    End Sub
    
    ' Visibility for each open design issue.
    ' If an issue is not marked as resolved, the corresponding
    ' button and label display.
    Sub GetIssueVisibility(control As IRibbonControl, _
                           ByRef returnedVal)
      Select Case control.ID
        Case "resolveDelayIssue"
          returnedVal = Not delayIssueResolved
        Case "delayIssue"
          returnedVal = Not delayIssueResolved
        Case "resolveEquipmentIssue"
          returnedVal = Not equipmentIssueResolved
        Case "equipmentIssue"
          returnedVal = Not equipmentIssueResolved
        Case "resolveLaborIssue"
          returnedVal = Not laborIssueResolved
        Case "laborIssue"
          returnedVal = Not laborIssueResolved
      End Select
    End Sub
    
    ' Called when the user clicks a resolve issue button.
    ' 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 is called to reset the UI, causing all controls
      ' to redisplay and executing all relevant callbacks.
      processRibbon.Invalidate
    End Sub
  8. On the File menu, click Save.

  9. 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 Customized Control Format tab that is located under the built-in Info tab. When you select the Customized Control Format tab, you can interact with the custom Backstage view page.

Figure 1. Custom Backstage view page

Custom Backstage view page

 

Read It

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 control the horizontal and vertical layout of controls added to the Backstage view page. The sample code also shows how to emphasize a group of controls by setting a group's display style.

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 of the RibbonUI object.

The following code snippet 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.

<!-- 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

'Store a reference to the ribbon for refreshing the UI.
Sub OnLoad(ribbon As IRibbonUI)
  Set processRibbon = ribbon
End Sub

Specify Control Layout

You may want to place controls horizontally on the page instead of using the default vertical layout. The following code example shows how to use a layoutContainer control to place controls either horizontally or vertically, by setting the layoutChildren attribute of the layoutContainer control. The first layoutContainer control sets the layoutChildren attribute to the default value of vertical. This also displays the Specification Detail editBox controls in a vertical column. The second layoutContainer control sets the layoutChildren attribute to horizontal. This displays the Specification Detail button controls in a horizontal row below the edit boxes.

<!-- The layoutChildren attribute places
      this set of controls vertically. -->
<!-- The GetSpecDetailText callback returns 
      a value to display for each editBox. -->
<layoutContainer id="specDetails" layoutChildren="vertical">
  <editBox id="specTitle" label="Title:        "
           getText="GetSpecDetailText" />
  <editBox id="specDesigner" label="Designer: "
           getText="GetSpecDetailText" />
  <editBox id="specEngineer" label="Engineer: "
           getText="GetSpecDetailText" />
  <editBox id="specTeam" label="Team:      "
           getText="GetSpecDetailText"/>
  <editBox id="specCost" label="Cost:        "
           getText="GetSpecDetailText"/>
</layoutContainer>
<!-- The layoutChildren attribute places 
      the buttons horizontally. -->
<layoutContainer id="specButtons" layoutChildren="horizontal">
  <button id="getCostBasis" 
          label="Get Cost Basis Info"/>
  <button id="getCostCodes" 
          label="Get Cost Codes"/>
  <button id="getTeamCodes" 
          label="Get Team Codes"/>
</layoutContainer>

Set a Group Style to Emphasize Status

There may be instances where you want to call attention to a particular group of controls based on some condition. The Open Design Issues group calls attention to itself when there are unresolved issues by displaying with a red highlight. Backstage view groups set their display style by using the getStyle attribute’s callback. This callback can return one of the following BackstageGroupStyle enumeration values:

  • BackstageGroupStyleNormal. The group has no special visual treatment.

  • BackstageGroupStyleWarning. The group is highlighted in yellow.

  • BackstageGroupStyleError. The group is highlighted in red.

The following custom UI XML example shows how to specify callbacks dynamically to define how controls are displayed on the page. The Open Design Issues group sets the getStyle attribute’s callback and the getHelperText attribute’s callback. These callbacks evaluate whether there are any unresolved issues and return the appropriate style and text. Each issue's Click to Resolve button and descriptive label set the getVisible attribute’s callback, hiding the controls after an issue is resolved. The resolve button also sets an onAction attribute’s callback to mark the issue as resolved.

<!-- The getStyle and getHelperText callbacks 
      dynamically set the Open Design Issues Group style 
      and text based on whether there are any open issues. -->
<group id="openDesignIssuesGroup" label="Open Design Issues"
       getStyle="GetIssuesStyle" 
       getHelperText="GetIssuesHelperText">
  <topItems>
    <!-- The layoutChildren attribute places 
          each set of issue controls horizontally. -->
    <!-- The onAction callback marks issues as resolved 
          when the user clicks the resolve button. -->
    <!-- The getVisible callback hides 
          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 getStyle attribute of the Open Design Issues group (with its corresponding GetIssuesStyle callback) and the getHelperText attribute (with the GetIssuesHelperText callback) emphasize the group when there are unresolved issues. Initially all issues are unresolved and the GetIssuesStyle callback returns the BackstageGroupStyleError enumeration value to emphasize the Open Design Issues group. After all issues are resolved, the GetIssuesStyle callback returns the BackstageGroupStyleNormal enumeration value to remove the emphasis. The getHelperText attribute’s callback, GetIssuesHelperText, works in parallel with the GetIssuesStyle callback by returning instructions about how to mark issues as resolved until all issues are resolved.

' Group style for the Open Design Issues Group.
' If all issues are not resolved the error style 
' emphasizes the group.
Sub GetIssuesStyle(control As IRibbonControl, _
                   ByRef returnedVal)
  If (delayIssueResolved And equipmentIssueResolved _
      And laborIssueResolved) Then
    ' This enumeration was renamed after the Office 2010 beta release.
    ' For the beta release, use the OutSpaceSlabStyle.OutSpaceSlabStyleNormal
    ' enumeration.
    returnedVal = BackstageGroupStyle.BackstageGroupStyleNormal
  Else
    ' This enumeration was renamed after the Office 2010 beta release.
    ' For the beta release, use the OutSpaceSlabStyle.OutSpaceSlabStyleError
    ' enumeration.
    returnedVal = BackstageGroupStyle.BackstageGroupStyleError
  End If
End Sub

'Helper Text for the Open Design Issues group.
' Text returned is based on the status of all issues.
Sub GetIssuesHelperText(control As IRibbonControl, _
                        ByRef returnedVal)
  If (delayIssueResolved And equipmentIssueResolved _
      And laborIssueResolved) Then
    returnedVal = "All issues are resolved."
  Else
    returnedVal = "Click resolve as issues are resolved."
  End If
End Sub

The following code example shows how the Click to resolve button and the issue label's getVisible attribute (with the GetIssueVisibility callback) hides issues after they are marked as resolved. The GetIssueVisibility value identifies the control to display and returns a value of True or False according to the resolved status of the related issue.

' Visibility for each Open Design Issue.
'If an issue is not marked as resolved, the corresponding
' button and label display.
Sub GetIssueVisibility(control As IRibbonControl, 
                       ByRef returnedVal)
  Select Case control.ID
    Case "resolveDelayIssue"
      returnedVal = Not delayIssueResolved
    Case "delayIssue"
      returnedVal = Not delayIssueResolved
    Case "resolveEquipmentIssue"
      returnedVal = Not equipmentIssueResolved
    Case "equipmentIssue"
      returnedVal = Not equipmentIssueResolved
    Case "resolveLaborIssue"
      returnedVal = Not laborIssueResolved
    Case "laborIssue"
      returnedVal = Not laborIssueResolved
  End Select
End Sub

The following code example shows how the onAction attribute’s callback of the Click to Resolve button, ResolveIssue, marks issues as resolved. The ResolveIssue callback identifies which button was clicked and marks the appropriate issue as resolved. After the issue is resolved, the Invalidate method of the RibbonUI object redisplays the Backstage view controls and displays the current resolved issues state. When the Invalidate method is called, the callback of the Open Design Issues group's getStyle attribute and the callback of the getHelperText attribute are executed again. The getVisible attribute’s callback for each Click to Resolve button and issue label is also executed again.

' Called when a  user clicks the Resolve issue button.
' 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 is called to reset the UI, causing all controls
  ' to redisplay and executing all relevant callbacks.
  processRibbon.Invalidate
End Sub
See It

Watch the video

> [!VIDEO https://www.microsoft.com/en-us/videoplayer/embed/8e1ff7d3-010a-4967-bcd2-553ad3c69807]

Length: 00:09:14

Click to grab code

Grab the Code

Explore It