Apply custom scorecard transforms to a PerformancePoint dashboard

 

Applies to: SharePoint Server 2010 Enterprise

You can use custom scorecard transforms in PerformancePoint Services in Microsoft SharePoint Server 2010 to change the appearance and content of scorecards. Transforms are especially useful for making global changes to a collection of published scorecards, without requiring you to edit scorecards individually in PerformancePoint Dashboard Designer. Although transforms run on all scorecards throughout a PerformancePoint Services instance, you can set conditions so that only specific scorecards are changed.

This article contains instructions for creating and installing a transform. The code example is written in the C# programming language and uses the Microsoft .NET Framework 3.5. You can paste the code into Microsoft Visual Studio and then edit as needed to make it work with your environment.

Important

This example is intended for demonstration only. It is provided AS IS without warranty of any kind, either express or implied. This includes any implied warranties of fitness for a particular purpose, merchantability, or non-infringement.

In this article:

  • Scenario overview

  • Scorecard transform prerequisites

  • Creating and installing a scorecard transform

Scenario overview

Suppose that you have created a PerformancePoint dashboard that contains a scorecard and several reports. For example, a basic dashboard that can be used to track inventory might resemble the following image.

Inventory dashboard

The dashboard displays the correct information, but with other reports on the page, it might be better to make the Inventory Rotation scorecard appear more concise. Suppose additionally that there are several other dashboards that contain various inventory scorecards, and that you want to reduce how all the scorecards are displayed. Rather than edit each one by using Dashboard Designer, you can create and apply a scorecard transform that displays how all those scorecards are displayed without actually changing the scorecards.

The transform described in this article reduces the size of how scorecards are displayed in dashboards. Specifically, it makes the following changes for all scorecards that include "Inventory" in their names:

  • Abbreviates KPI display names.

  • Changes the background color of the Actual column cells to reflect the indicator color.

  • Removes all columns that are not Actual column types.

Tip

You can use your own PerformancePoint dashboard or re-create our example dashboard. For information about how to create a dashboard that resembles our example dashboard, see Create a baseline PerformancePoint dashboard to use with custom extensions scenarios.

Scorecard transform prerequisites

Identify or create a PerformancePoint dashboard that contains a scorecard that resembles the scorecard that is shown in the following image.

Inventory Rotation scorecard

The scorecard transform described in this article is based on the following assumptions:

  • The scorecard contains key performance indicator (KPI) names on rows.

  • The scorecard contains only one Actual column.

  • The scorecard contains a Target column that uses an indicator that has three bands: On Target, Slightly Off Target, and Off Target.

To create the transform, you must have Visual Studio installed on the application server where PerformancePoint Services is installed. To download trial versions of Visual Studio, see Visual Studio Downloads (https://go.microsoft.com/fwlink/p/?LinkId=220177).

To install the transform, you must have sufficient permissions to register an assembly in the global assembly cache, copy files to the local directory, and edit the PerformancePoint Services Web.config file. In addition, you may need permissions to recycle the Internet Information Services (IIS) application pool that the transform worker process is running in.

Creating and installing a scorecard transform

The following instructions are based on the assumption that Visual Studio is installed on the application server that is running PerformancePoint Services. These instructions are based on the Visual Studio 2010 Professional user interface. They might vary in other versions.

To copy PerformancePoint Services assemblies from the global assembly cache

  1. Create a folder named to store local copies of PerformancePoint Services assemblies. These instructions assume that you create a folder named PpsDlls on the root of the C drive.

  2. Start the command prompt console as an administrator.

  3. Run the following commands in order:

    cd %WINDIR%\assembly\GAC_MSIL\Microsoft.PerformancePoint.Scorecards.Client\14.0.0.0__71e9bce111e9429c
    
    copy Microsoft.PerformancePoint.Scorecards.Client.dll C:\PpsDlls
    
    cd %WINDIR%\assembly\GAC_MSIL\Microsoft.PerformancePoint.Scorecards.ServerCommon\14.0.0.0__71e9bce111e9429c
    
    copy Microsoft.PerformancePoint.Scorecards.ServerCommon.dll C:\PpsDlls
    

To create and modify the transform

  1. In Visual Studio, click New, and then select Project.

  2. In the New Project dialog box, select the Visual C# template, .NET Framework 3.5., and the Class Library project template.

  3. Type ShrinkScorecardTransform as the name for the project, and then click OK.

  4. Replace the boilerplate contents of the class by using the following code.

    using System;
    using System.Drawing;
    using System.Collections.Generic;
    using Microsoft.PerformancePoint.Scorecards;
    using Microsoft.PerformancePoint.Scorecards.Extensions;
    
    namespace Microsoft.PerformancePoint.SDK.Samples.ScorecardTransforms.PreRender
    {
    
        // PreRender scorecard transform sample. 
        public class ShrinkScorecardTransform : IGridViewTransform
        {
    
            // Set the transform type, which defines when the transform runs.
            public GridViewTransformType GetTransformType()
            {
                return GridViewTransformType.PreRender;
            }
    
            // Return the string identifier of your transform.
            public string GetId()
            {
                return "ShrinkScorecard";
            }
    
            // Run the transform. 
            public void Execute(GridViewData viewData, PropertyBag parameters, IGlobalCache cache)
            {
                GridFormatInfo indicatorBackground = new GridFormatInfo();
    
                // Verify that viewData is not null.
                if (viewData == null)
                {
                    throw new ArgumentException("Parameter cannot be null", "viewData");
                }
    
                Scorecard scorecardInLocalCache = cache.GetScorecard(viewData.ScorecardLocation);
    
                // This transform runs only on scorecards that contain the specified string in their names. 
                // Edit 1. Change the string value to test on your own scorecards.
                if (scorecardInLocalCache.Name.Text.Contains("Inventory"))
                {
                    List<GridHeaderItem> rowHeaders = viewData.RootRowHeader.GetAllHeadersInTree();
                    List<GridHeaderItem> leafColumnHeaders = viewData.RootColumnHeader.GetAllLeafHeadersInTree();
    
                    GridDisplayElementIndicator indicatorElement = new GridDisplayElementIndicator();
    
                    // Loop through the row headers.
                    foreach (GridHeaderItem rowHeader in rowHeaders)
                    {
                        // Abbreviate KPI display names.
                        if (rowHeader.HeaderType == ScorecardNodeTypes.Kpi)
                        {
                            // Replace strings in row headers with abbreviations.
                            // Edit 2. Change the string values to test on your own scorecards.
                            string displayText = rowHeader.DisplayText;
                            displayText = displayText.Replace("Inventory", "Inv");
                            displayText = displayText.Replace("Quantity", "Qty");
                            rowHeader.DisplayText = displayText;
                        }
    
                        // Create containers to store actual cell coordinates.
                        GridCell actualCell = new GridCell();
                        GridHeaderItem actualColumnHeader = new GridHeaderItem();
    
                        // Loop through the column headers to reformat the actual cell.
                        foreach (GridHeaderItem columnHeader in leafColumnHeaders)
                        {
    
                            // Get the scorecard cell at the intersection of the current row and column headers.
                            GridCell cell = viewData.Cells[rowHeader, columnHeader];
    
                            // If this is an actual cell, store its coordinates.
                            if ((columnHeader.HeaderType == ScorecardNodeTypes.KpiActual) && (cell.DisplayElements.Count > 0))
                            {
                                actualCell = cell;
                                actualColumnHeader = columnHeader;
                            }
    
                            // Get the indicator value for the target cell. A target cell can contain multiple
                            // display elements, such as a target value, an indicator icon, and a variance value.
                            if (columnHeader.HeaderType == ScorecardNodeTypes.KpiTarget)
                            {
                                if (cell.DisplayElements != null && cell.DisplayElements.Count > 0)
                                {
                                    foreach (GridDisplayElement element in cell.DisplayElements)
                                    {
                                        if (element.GetType() == indicatorElement.GetType())
                                        {
                                            indicatorBackground = cell.ResolvedFormatInfo;
    
                                            // Look for the default Text values for a native tri-state indicator.
                                            switch (element.Text)
                                            {
                                                case "On Target":
                                                    indicatorBackground.BackColor = new GridColor(Color.PaleGreen);
                                                    break;
                                                case "Slightly Off Target":
                                                    indicatorBackground.BackColor = new GridColor(Color.Yellow);
                                                    break;
                                                case "Off Target":
                                                    indicatorBackground.BackColor = new GridColor(Color.LightCoral);
                                                    break;
                                            }
    
                                            // Reformat the actual cell.
                                            actualCell.FormatInfo = indicatorBackground;
                                            viewData.Cells[rowHeader, actualColumnHeader] = actualCell;
                                            break;
                                        }
                                    }
                                }
                            }
    
                            // Remove columns that are not Actual columns.
                            if (columnHeader.HeaderType != ScorecardNodeTypes.KpiActual)
                            {
                                if (columnHeader.Parent != null)
                                {
                                    columnHeader.Parent.Children.Remove(columnHeader);
                                }
                                else
                                {
                                    viewData.RootColumnHeader.Children.Remove(columnHeader);
                                }
                            }
                        }
                    }
                }
            }  
        }
    }
    
  5. Find the Execute method in the code, and then change variables to match your environment, as follows:

    To make the code work in your environment

    1. Change the string variable "Inventory" to match the name of the scorecards that you want to run the transform on. For example, if you want the transform to run on all scorecards with "South" in their names, replace "Inventory" with "South".

      // Edit 1. Change the string value to test on your own scorecards.
      if (scorecardInLocalCache.Name.Text.Contains("Inventory"))
      
    2. Change the string variables to match parts of KPI names that you want to abbreviate.

      // Edit 2. Change the string values to test on your own scorecards.
      string displayText = rowHeader.DisplayText;
      displayText = displayText.Replace("Inventory", "Inv");
      displayText = displayText.Replace("Quantity", "Qty");
      
  6. In the Solution Explorer pane (located on the right side of the Visual Studio application), rename the Class1.cs class to ShrinkScorecardTransform.cs.

  7. Right-click the project node, and then select Add Reference.

  8. In the Add Reference dialog box, click the Browse tab, and then navigate to the C:\PpsDlls folder.

  9. Select the two assemblies that you copied in the "To copy PerformancePoint Services assemblies from the global assembly cache" procedure, and then click OK.

  10. Reopen the Add Reference dialog box, and then click the .NET tab.

  11. Select the System.Drawing assembly, and then click OK.

To sign and build the transform assembly

  1. In Solution Explorer, right-click the project node, and then select Properties.

  2. Click the Signing tab, and then select the Sign the assembly check box.

  3. In the Choose a strong name key file list, select New to generate a new key.

  4. In the Create Strong Name Key dialog box, type the name that you want to use for the key.

  5. (Optional) Provide a password for the key.

  6. Click OK.

  7. In the Solution Explorer pane, right-click the project node, and then select Build.

    The build status displays in the lower-left-hand corner of the Visual Studio application. If the build fails, refer to the Error tab for troubleshooting information.

To install the transform

  1. Copy the transform assembly to the global assembly cache. To do this, use the following procedure:

    To copy the transform assembly to the global assembly cache

    1. Using Windows Explorer, navigate to the output folder that contains your transform assembly. By default, it is created in the bin\Debug or bin\Release folder in your Visual Studio project files. Example: C:\Users\mboyer\Documents\Visual Studio 2010\Projects\ShrinkScorecardTransform\ShrinkScorecardTransform\bin\Debug.

    2. Open a separate instance of Windows Explorer, and then navigate to the global assembly cache in the default path C:\Windows\assembly.

    3. Drag your transform assembly to the global assembly cache. If you cannot add the assembly to the global assembly cache, close the two instances of Windows Explorer, reopen them with administrative privileges, and then repeat steps 1a and 1b.

    4. In the global assembly cache, right-click your transform assembly, and then click Properties.

    5. In the Properties dialog box, find the version, culture, and public key token of the assembly. Make a record of these values.

      Note

      This procedure describes one way to register an assembly in the global assembly cache. For information about other ways to register assemblies, see How to: Install an Assembly into the Global Assembly Cache (https://go.microsoft.com/fwlink/p/?LinkId=220181).

  2. Navigate to the PerformancePoint Services Web.config file in the default path %PROGRAMFILES%\Microsoft Office Servers\14.0\WebServices\PpsMonitoringServer.

  3. Open the Web.config file in a text editor, such as Notepad.

    Important

    As a best practice, make a copy of the Web.config file before editing it.

  4. Find the opening tag for the CustomViewTransforms element, and then paste the following code directly under it.

    <add key="ShrinkScorecard" value="Microsoft.PerformancePoint.SDK.Samples.ScorecardTransforms.PreRender.ShrinkScorecardTransform, ShrinkScorecardTransform, Version=[the version of your assembly], Culture=[the culture of your assembly], PublicKeyToken=[the public key token of your assembly]"/>
    
  5. Edit the pasted code, replacing the placeholder values with the values that you recorded in step 1e. Example:

    <add key="ShrinkScorecard" value="Microsoft.PerformancePoint.SDK.Samples.ScorecardTransforms.PreRender.ShrinkScorecardTransform, ShrinkScorecardTransform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=fa525c8383a44a52"/>

  6. Save and then close the Web.config file.

    The transform is now applied to new and existing scorecards (and Strategy Map reports) that are in your environment. If the scorecard views are cached, you may not see the transform changes. In this case, you can recycle the Internet Information Services (IIS) application pool for PerformancePoint Services that the transform process is running in and then refresh the dashboard page.

To recycle the PerformancePoint application pool

  1. In the Windows Start menu, select Run. In the Run dialog box, type inetmgr and then click OK.

  2. In Internet Information Services (IIS) Manager, expand the server node, and then click Application Pools.

  3. Find the application pool that is running PerformancePoint Services, as follows:

    To locate the PerformancePoint application pool

    1. Right-click an application pool name, and then select View Applications.

      Tip

      The target application pool is the frequently the one that is running the most applications, as shown in the Applications column.

    2. In the Applications pane, expand the Physical Path column and look for the path that ends with "PpsMonitoringServer."

      If the list does not contain the path for "PpsMonitoringServer," click Remove filter to return the list of all applications.

    3. Note the application pool name that is listed in the respective Application Pool column.

  4. In the Connections pane, click Application Pools.

  5. In the Application Pools pane, right-click the target application pool, and then select Recycle.

  6. Refresh the dashboard page in your browser.

See Also

Concepts

Create a baseline environment for a BI test environment

Other Resources

Overview of Scorecard Transforms
How to: Create Scorecard Transforms