Part 1: Setting up the Visio solution and customizing the ribbon

Office 2010

Summary:  The first article in a series of four articles about how to export Microsoft Visio 2010 shapes to Microsoft PowerPoint 2010. Part 1 discusses how to create a Visio 2010 add-in project in Visual Studio 2010, how to customize the Visio 2010 ribbon, and how to look up PowerPoint shape conversion values for Visio shapes.

Despite any visual similarities, the shapes included in the built-in Microsoft Visio 2010 stencils and the built-in shapes included in Microsoft PowerPoint 2010 are very different programmatically. Because of these differences, drawings cannot be easily transferred from Visio to PowerPoint. Traditionally, transferring shapes from Visio to PowerPoint relied on copying and pasting the shapes as pictures or using OLE.

The two applications work with shapes in a very different way. To Visio, each "type" of shape in the Shapes window is actually content (a "master" shape) that is contained in another document (a "stencil" or .vss file). When you drag a shape from the Shapes window to the drawing page, Visio basically creates a copy of the master shape. Most of the values that are used to specify the formatting for the Visio.Shape object are contained as formulas in the ShapeSheet, and must be accessed by referencing the appropriate cells. One benefit is that users can create and share custom stencils and master shapes to define new data fields, and to set their own business logic in a shape.

In PowerPoint, the difference between shapes is built into the object model. The MsoAutoShapeType enumeration predefines the type of shapes that can be created in PowerPoint. (Note that Microsoft Word 2010 and Microsoft Excel 2010 also use the MsoAutoShapeType enumeration to define shapes.) The Shape object uses class properties to specify formatting. The shapes do not allow for new data fields or custom logic (without programmatic customization).

To address some of these issues, the Exporting Visio 2010 Diagrams to PowerPoint 2010 add-in for Visio 2010, available for download from the MSDN Samples Gallery, recreates a diagram as individual shapes on a PowerPoint 2010 slide. The add-in converts a subset of the built-in Visio shapes to analogous shapes in PowerPoint. It reads the formatting data in the ShapeSheet of the Visio.Shape object, converts that data to values and data types that PowerPoint can use, and then constructs a new Shape object on a slide. The add-in uses the spatial and formatting values of the original Visio.Shape object to set the properties of the new Shape object so that it looks similar in position (from the top-left corner of the Visio page and the PowerPoint slide) and visual effect.

For the Visio shapes that do not have analogs in PowerPoint, the add-in creates pictures of each shape and then pastes them onto the PowerPoint slide. Each picture is resized to match the original Visio shape and positioned to correspond to the spatial layout of the original Visio diagram.

At the heart of the add-in is the ShapeConversion class, which gets the data from ShapeSheet cells of the Visio.Shape objects, converts the values, and then stores the data. The ShapeConversion class gets and converts the following formatting values from the Visio.Shape object:

  • Width and height

  • X-axis and y-axis position, measured from the top-left corner of the Visio drawing page

  • Shape text, font, font color, and font size

  • Paragraph alignment (vertical and horizontal) and text orientation

  • Text block size and spatial relationship to the shape

  • Fill color and transparency

  • Line color, weight, pattern, and line end styles

  • Shadow pattern, type, color, transparency, size, and spatial offset

  • Beginning and end points for connector shapes

Note Note

In the interest of readability, this article describes how to convert only a few of the formatting features in the previous list and focuses mainly on shapes from the Basic Flowchart (US units) stencil. The files available for download from the Samples Gallery contain the complete code that is required to convert all the formatting values.

All these values are exposed as read-only properties to any code that creates an instance of the ShapeConversion class. Thus, constructing the shapes in PowerPoint only requires matching the Shape properties with the equivalent properties of a ShapeConversion object.

In this article, you learn how to create a limited version of the Exporting Visio 2010 Diagrams to PowerPoint 2010 add-in by using Microsoft Visual Studio 2010, C# or Visual Basic, the Microsoft .NET Framework 4, and the primary interoperability assemblies (PIAs) for Visio 2010 and PowerPoint 2010. You also learn about the underlying programming concepts behind the add-in, including the following:

  • How to customize the Visio 2010 ribbon with custom buttons and icons.

  • How to control PowerPoint 2010 from a Visio add-in.

  • How to access and store multiple ShapeSheet values from a Visio Shape object.

  • How to create a connected diagram programmatically in PowerPoint 2010.

The complete code files for the Exporting Visio 2010 Diagrams to PowerPoint 2010 add-in are available for download from the Samples Gallery.

Visual Studio 2010 provides project templates to create basic add-ins for most Office 2010 applications, including Visio 2010 and PowerPoint 2010, in both Visual Basic and C#. The Exporting Visio 2010 Diagrams to PowerPoint 2010add-in is contained in a Visio 2010 add-in solution.

Use the following procedure to create a new Visio 2010 add-in project in Visual Studio 2010.

To create a Visio 2010 add-in project in Visual Studio 2010

  1. On the File tab in Visual Studio 2010, choose New, and then click Project.

  2. In the Installed Templates list, expand either Visual Basic or Visual C#.

  3. Expand the Office node, and then click 2010.

  4. Click Visio 2010 Add-in.

  5. Name the project ExportToPPT, specify the location where you want to save the project, and then click OK.

The add-in uses classes from the Microsoft.Office.Interop.PowerPoint and System.Windows.Forms libraries. You must add a reference to these libraries in your project. Use the following procedure to add the references to your project.

To add a library reference to a project in Visual Studio 2010

  1. In Solution Explorer, right-click the project name (ExportToPPT), and then click Add Reference.

  2. In the Add Reference dialog box, click the .NET tab.

  3. In the Component Name list, select Microsoft.Office.Interop.PowerPoint (version 14.0.0.0) and System.Windows.Forms, and then click OK.

The Exporting Visio 2010 Diagrams to PowerPoint 2010 add-in uses a custom tab that has two custom buttons in the Visio 2010 ribbon to execute the code. Although the ribbon customization is not strictly necessary to export a Visio 2010 diagram to PowerPoint 2010, it makes it easier to use the add-in. For more information about how to customize the Visio 2010 ribbon, see Customizing the Ribbon in Visio 2010 by Using a Visual Studio 2010 Add-In.

Use the following procedure to add a new ribbon XML file to the project to contain the customization for the Visio 2010 ribbon.

To add a ribbon extensibility item to the project

  1. In Solution Explorer, right-click the project name (ExportToPPT), point to Add, and then click New Item.

  2. Select Ribbon (XML).

  3. Accept the default name (Ribbon1.vb or Ribbon1.cs) and then click Add.

  4. In Solution Explorer, right-click the project name (ExportToPPT), and then click Properties.

  5. Click Resources.

  6. From Solution Explorer, drag the ribbon XML (Ribbon1.xml) file onto the Resources design surface.

Visual Studio 2010 adds two files to the project: an XML file (Ribbon1.xml) that contains the markup for the ribbon customization, and a code-behind file (Ribbon1.vb or Ribbon1.cs) to contain the callback functions for the ribbon UI elements. The ribbon XML file includes the names and attributes for the custom tabs, groups, and buttons that are added to the Visio 2010 ribbon. The code-behind file, Ribbon1.vb or Ribbon1.cs, contains the code that loads the ribbon into the application and the callback methods to call when the buttons on the ribbon are clicked.

You can add two buttons on a new Export tab in the Visio 2010 ribbon, with one button labeled Export Page and the other labeled Export Diagram. To create these two buttons, the markup in the Ribbon1.xml file must include a button element for each button. The attributes for these two button elements determine the callback methods to call when the buttons are clicked. Each button includes an onAction attribute that specifies the method to call when the button is clicked. In this add-in, the Export Page button calls ExportPage method and the Export Diagram button calls the ExportDiagram method.

This add-in also displays a custom button image for each new button on the custom ribbon. To do this, the button tags specify the GetImages method as a value for the optional getImage attribute. The callback method is raised when the ribbon loads and determines which button image to display in the custom UI. The method returns a reference to the appropriate image file from the project resources.

Note Note

For a custom button, you can also select one of the built-in UI images that are included with Visio 2010. Instead of providing a value for the getImages attribute, you can set the imageMso attribute of the button element to the ID of the button image that you want. To get a list of valid values that you can use for the imageMso attribute, download the macro-enabled Word document Office 2010 Add-In: Icons Gallery.

In the Ribbon1.xml file, replace all the content in the tabs element with the following XML, which adds a new tab, a new group, and two new buttons to the Visio 2010 ribbon.

<tab id="tabExport" label="Export">
    <group id="grpExport" label="Export to PowerPoint">
        <button id="btnExportPage" size="large" label="Export Page"
            onAction="ExportPage" getImage="GetImages" showImage="true" />
        <button id="btnExportDiagram" size="large" label="Export Diagram"
            onAction="ExportDiagram" getImage="GetImages" showImage="true"/>
    </group>
</tab>

Custom button images are external resources that you must add to your project before you can load them into the custom ribbon. These images can be in one of several graphics file formats that include PNG, JPG, BMP, and SVG. When displayed, the images are scaled to fit the size that is specified by the size attribute of the button element. To avoid image distortion, design your UI elements to match the display dimensions: 32 pixels by 32 pixels for large icons, and 16 pixels by 16 pixels for small icons.

Use the following procedure to add new custom button icons to the Visual Studio 2010 project.

To add a custom button UI icon to the project

  1. In Solution Explorer, right-click the project name (ExportToPPT), and then click Properties.

  2. Click the Resources tab.

  3. Click the arrow next to Add Resource, and then click Add Existing File.

  4. Browse to the folder that contains the icons for your custom UI element.

  5. Select the icon that you want, and then click Open.

Next, add code to the ThisAddIn class to enable the customized ribbon when the add-in loads. At the bottom of the ThisAddIn class in the ThisAddIn.vb or ThisAddIn.cs file, add the following code, which returns an object that implements the IRibbonExtensibility class.

protected override Microsoft.Office.Core.IRibbonExtensibility 
    CreateRibbonExtensibilityObject()
{
    // Use the name of the class specified in the Ribbon.cs file.
    return new Ribbon1();
}

Now create the GetImages callback method in the Ribbon1.vb or Ribbon1.cs file that loads the custom UI icons into the ribbon when the add-in loads. Note that the button click event automatically passes in a reference to the button that raised the event. The callback method gets the Id property of the control, and then determines the image to return.

In the Ribbon Callbacks region of the Ribbon class in the Ribbon1.vb or Ribbon1.cs file, add the following code, which returns one of two image files from the assembly resources, depending on the control that called the method.


public object GetImages(Office.IRibbonControl control)
{
     // Use the ID attribute of the calling UI element to determine the image
     // to return.
    if (control.Id == "btnExportPage")
    {
        return Properties.Resources.ExportVisioPage_32x32;
    }
    else {
        return Properties.Resources.ExportVisioDiagram_32x32;
    }
}

The Exporting Visio 2010 Diagrams to PowerPoint 2010 add-in has two separate but similar modes, each represented by a button in the custom ribbon. Each mode has its own respective callback method that are contained in the Ribbon class of the Ribbon1.vb or Ribbon1.cs file. The ExportPage callback method is the most basic mode of the add-in; it captures a reference to the active page in the current Visio drawing and exports the shapes on that page to a single slide in a new PowerPoint 2010 presentation. The ExportDiagram method expands the scope of ExportPage by exporting the shapes on each page in the active Visio document to a slide in a new PowerPoint 2010 presentation.

Also included in the Ribbon class is a helper method, Validate, which is called by the callback methods. This method checks the Visio application and document before the add-in executes any other code. Because the Validate method uses a message box to display any issues, you must import the System.Windows.Forms library into the Ribbon class.

At the top of the Ribbon1.vb or Ribbon1.cs file, add the following code, which imports the System.Windows.Forms and Microsoft.Office.Interop.Visio libraries.

using System.Windows.Forms;
using Visio = Microsoft.Office.Interop.Visio;

The callback methods and internal Validate method of the Ribbon class (discussed later) use several global variables:

  • errMsg—indicates whether an error occurred

  • vsoApp—represents the Visio application

  • myAddIn—represents the add-in

In the declarations region of the Ribbon class in the Ribbon1.vb or Ribbon1.cs file, add the following code to create the class fields errMsg, vsoApp, and myAddIn.

public bool errMsg; 
private Visio.Application vsoApp;
private ThisAddIn myAddIn;

The ExportPage method first captures a reference to the Visio application and the ThisAddIn class. Before it executes any other code, the method makes a call to the internal Validate method, passing in a value of false for the checkAllPages parameter. If the Validate method returns a value of true, the method calls the ExportPage method of the ThisAddIn class.

The ExportDiagram method also captures a reference to the Visio application and the ThisAddIn class. It then calls the Validate method, passing in a value of true for the checkAllPages parameter. If the Validate method returns a value of true, the ExportDiagram method calls the ExportAllPages method of the ThisAddIn class.

In the Ribbon Callbacks region of the Ribbon class in the Ribbon1.vb or Ribbon1.cs file, add the following code. The code creates the callback methods ExportPage and ExportDiagram, which call the myAddIn.ExportPage and myAddIn.ExportAllPages methods, respectively.


public void ExportPage(global::Microsoft.Office.Core.IRibbonControl control)
{
    vsoApp = Globals.ThisAddIn.Application;
    myAddIn = ExportToPPT.Globals.ThisAddIn;

    // Check for conditions that affect conversion or application errors.
    errMsg = false;
    if (!(Validate(false))) {
        return;
    }

    // Export shapes on the active Visio page to PowerPoint.
    myAddIn.ExportPage();
}

public void ExportDiagram(global::
    Microsoft.Office.Core.IRibbonControl control)
{
    vsoApp = Globals.ThisAddIn.Application;
    myAddIn = ExportToPPT.Globals.ThisAddIn;

    // Check for conditions that affect conversion or application errors.
    errMsg = false;
    if (!(Validate(true))) {
        return;
    }

    // Export all the shapes on each page of the Visio drawing.
    myAddIn.ExportAllPages();
}

As you can see, the ribbon callback methods call a Validate method before they execute any other code. The Validate method provides an initial layer of error handling by checking the state of the active Visio document against the basic assumptions that are used by the add-in code. The method has a single parameter, checkAllPages, which determines whether the method examines each page in the active Visio document or just the currently active page. The method returns the doContinue variable as a Boolean value, where a value of false indicates that the state of the Visio application or document does not pass the checks that the method performed.

The Validate method first checks whether the Visio application has any open documents. This check must occur before any other code in the ribbon callbacks occur because any references to the Application.ActiveDocument property raises an exception if no documents are open in the application. If the Application.Documents collection contains no items, the doContinue variable is set to false and the method exits. (In this situation, the add-in silently fails from the user perspective.)

Next, the Validate method compares the dimensions of the Visio page (or pages) against the default slide dimensions in PowerPoint. The default Blank template in PowerPoint 2010 is 7.5 inches high by 10 inches wide in landscape view, which is smaller than the page dimensions of many Visio templates. Although the add-in code executes successfully even if the Visio page is larger than the PowerPoint slide, the spatial translation between the two applications might behave unpredictably. For example, shapes could be exported off the edges of the PowerPoint slide if the Visio page is larger. Thus, if the method calculates that the Visio page is larger than 7.5 inches by 10 inches, it asks whether the user wants to continue with the operation. The method then continues to execute, or exits, depending on the user input.

If the Validate method finishes execution, it returns the doContinue variable as true to the calling code.

In the Helpers region of the Ribbon class in the Ribbon1.vb or Ribbon1.cs file, add the following code, which checks the state of the Visio application and then returns a Boolean value.


private bool Validate(bool checkAllPages)
{

    bool doContinue = true;

    // Check to see whether there are any documents currently open in Visio.
    if ((vsoApp.Documents.Count < 1))
    {
        doContinue = false;
        return doContinue;
    }

    Visio.Document vsoDoc = vsoApp.ActiveDocument;
    Visio.Pages vsoPages = vsoDoc.Pages;
    Visio.Page vsoPage = default(Visio.Page);
    int count = 0;
    int num = 0;

    // Set the scope within the Visio drawing to check for page dimensions.
    if (checkAllPages)
    {
        num = 1;
        count = vsoPages.Count;
    }
    else
    {
        num = vsoApp.ActivePage.Index;
        count = vsoApp.ActivePage.Index;
    }

    // Iterate through the page or pages in the Visio document. 
    for (int x = num; x <= count; x++)
    {
        vsoPage = vsoPages.get_ItemU(x);

        // Check the height and width of the Visio page against the 
        // default PowerPoint slide dimensions.
        // Normal page dimensions in Visio are 8.5 x 11 inches (landscape). 
        // Normal slide dimensions in PowerPoint are 7.5 x 10 inches (landscape).
        if (((vsoPage.PageSheet.get_Cells("PageHeight").
            get_Result(Visio.VisUnitCodes.visInches) > 7.5) | 
            (vsoPage.PageSheet.get_Cells("PageWidth").
            get_Result(Visio.VisUnitCodes.visInches) > 10)) &
            !errMsg)
        {
            // Display a message to the user if it has not displayed
            // previously.
            DialogResult userInput = MessageBox.Show("Some of the pages are "
                "larger than a default PowerPoint slide. \n" + 
                "Shapes may appear off the edge of the resulting slide." + 
                "\n\n Continue?", "Export Visio to PowerPoint", 
                MessageBoxButtons.OKCancel);
            errMsg = true;

            // Stop executing the running code if the user selects Cancel.
            if ((userInput == System.Windows.Forms.DialogResult.Cancel))
            {
                doContinue = false;
            }
       }
    }

    // Return the value of the doContinue variable to the calling method.
    return doContinue;
}

Show:
© 2014 Microsoft