Creating PowerPoint 2007 Presentations Based on Word Documents by Using Visual Studio 2005 Tools for the Office System SE

Summary:   Create a Microsoft Office PowerPoint 2007 presentation based on a Microsoft Office Word 2007 document containing an article or book excerpt.

Office Visual How To

Applies to:   2007 Microsoft Office System, Microsoft Office PowerPoint 2007, Microsoft Office Word 2007, Microsoft Visual Studio 2005, Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System Second Edition

Ken Getz, MCW Technologies, LLC

October 2007

Overview

Imagine that you created a Microsoft Office Word 2007 document that contains an article or a book chapter. You want to create a Microsoft Office PowerPoint 2007 presentation based on the same content. In PowerPoint 2007, you can import an outline from a Word 2007 document, but the results might not be as professional as you want your slide presentation to look. In your presentation, you want to include an "Agenda" slide that lists all the level 2 headings. You want to display the Agenda slide between topics of the presentation, with the current topic highlighted and previous topic titles shaded or dimmed. Finally, you might want to include a single slide for each heading, so you can fill in the specific details on each topic.

In this Office Visual How-to article, you create an add-in for Word 2007 by using Visual Studio 2005 Tools for the 2007 Microsoft Office System Second Edition. The add-in takes the structure of the current Word 2007 document, gathers information about all the headings, and creates a basic PowerPoint 2007 presentation, with corresponding Agenda and topic slides.

See It Creating PowerPoint 2007 Presentations

Watch the Video

Length: 10:39 | Size: 8.8 MB | Type: WMV file

Code It | Read It | Explore It

Code It

In this example, you create a Microsoft Office Fluent Ribbon customization that adds a button to the Add-Ins tab in Word 2007. Clicking the button creates a new PowerPoint 2007 presentation based on the currently loaded Word 2007 document. To demonstrate the technique, follow these steps.

To create a new button on the Word 2007 Add-Ins tab

  1. In Visual Studio 2005, create a new Visual Studio 2005 Tools for Office Second Edition add-in for Word 2007. Name the new project CreatePresentationAddIn.

  2. In Solution Explorer, right-click the project, and then click Add New Item.

  3. In the Add New Item dialog box, select Ribbon support.

  4. Click Add to insert the new Office Fluent Ribbon customization.

  5. Modify the new Ribbon1.xml file, replacing the existing content with the following XML.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnLoad">
      <ribbon>
        <tabs>
          <tab idMso="TabAddIns">
            <group id="MyGroup"
            label="Visual How-To">
              <button id="button1"
                size="large"
                label="Create PPT"
                screentip="Create presentation based on the current document."
                onAction="OnClick"
                imageMso="MicrosoftPowerPoint" />
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    
  6. In Solution Explorer, right-click the CreatePresentationAddIn project, and click Properties.

  7. In the Properties pane, click the Resources tab.

  8. In Solution Explorer, drag the Ribbon1.xml file into the Properties pane to add the Ribbon1.xml file as a project resource.

  9. Close the Properties pane, and click Yes when you are prompted to save.

  10. In the Ribbon1.vb or Ribbon1.cs file, uncomment the ThisAddIn partial class.

  11. In Microsoft Visual C# only, at the top of the code file, add the following using statement.

    using Word=Microsoft.Office.Interop.Word;
    
  12. In the Ribbon1 class, modify the existing GetCustomUI implementation so that it retrieves the Ribbon1 resource.

    In Visual C#, expand the IRibbonExtensibility members code region to find the procedure.

    Return My.Resources.Ribbon1
    
    return Properties.Resources.Ribbon1;
    
  13. In the Ribbon1 class, add the following callback procedure. Click the new button on the Office Fluent Ribbon to call this procedure.

    Public Sub OnClick(ByVal control As Office.IRibbonControl)
    End Sub
    
    public void OnClick(Office.IRibbonControl control)
    {
    }
    

Save the project, and run it. In Word 2007, on the Office Fluent Ribbon, click the Add-Ins tab, and verify that the new button appears. Close Word 2007, and return to Visual Studio 2005.

To programmatically interact with the PowerPoint 2007 object model, you must add a reference to the appropriate type library in your project.

To add a reference to the type library

  1. In Solution Explorer, right-click the project, and then click Add Reference.

  2. In the Add Reference dialog box, click the COM tab, and then select the Microsoft PowerPoint 12.0 Object Library reference.

  3. Click OK to add the reference.

Next, you want to store all the code that creates the PowerPoint 2007 presentation.

To store the code that creates the PowerPoint 2007 presentation

  1. Select Project, and then click Add Class.

  2. Name the new class DocToPPT, and click Add to insert the new class.

  3. At the top of the DocToPPT.vb or DocToPPT.cs file, add the following statements.

    Imports System.Collections.Generic
    Imports PowerPoint = Microsoft.Office.Interop.PowerPoint
    Imports Office = Microsoft.Office.Core
    
    using PowerPoint = Microsoft.Office.Interop.PowerPoint;
    using Word = Microsoft.Office.Interop.Word;
    using Office = Microsoft.Office.Core;
    using System.Windows.Forms;
    
  4. In the DocToPPT class, add the following private class to maintain information about the various headings within the document.

    Private Class HeadingInfo
      Public Text As String
      Public Level As Integer
      Public Index As Integer
    
      Public Sub New(ByVal text As String)
        Me.Text = text
      End Sub
    End Class
    
    private class HeadingInfo
    {
      public string Text;
      public int Level;
      public int Index;
    
      public HeadingInfo(string text)
      {
        this.Text = text;
      }
    }
    
  5. Add the following declarations to the DocToPPT class to store heading information and to refer to the host Application object.

    Private Shared allHeadings As List(Of HeadingInfo)
    Private Shared level2Headings As List(Of HeadingInfo)
    Private Shared level1Headings As List(Of HeadingInfo)
    Private Shared Application As Word.Application = _
      Globals.ThisAddIn.Application
    
    private static List<HeadingInfo> allHeadings;
    private static List<HeadingInfo> level2Headings;
    private static List<HeadingInfo> level1Headings;
    private static Word.Application Application = 
      Globals.ThisAddIn.Application
    
  6. Add the following procedure to the DocToPPT class.

    This procedure calls the GetCrossReferenceItems method to retrieve all the headings from the Word document, named c. This hands back an array, stored in a VBA Variant value. The common language runtime treats this as an Object type, and you must cast it as an Array before you can access its contents. The code loops through all the items in the array and determines the heading level for each heading by examining the number of leading spaces on each heading; more spaces indicates a lower level of heading. The code creates several lists of headings that it uses when the PowerPoint 2007 presentation is created.

    Private Shared Sub GetHeadings()
      Dim spaces As New String(" "c, 8)
    
      ' Get all the headings in the current document.
      Dim doc As Word.Document = Application.ActiveDocument
      Dim headings As Object = _
       doc.GetCrossReferenceItems(Word.WdReferenceType.wdRefTypeHeading)
    
      ' Convert the variant array into a .NET Array.
      Dim items As Array = CType(headings, Array)
    
      ' Loop through all the items in the array. They are
      ' numbered using a 1-based index, because
      ' the array came from VBA.
      For i As Integer = _
       items.GetLowerBound(0) To items.GetUpperBound(0)
    
        ' Get the text from the array.
        Dim itemText As String = items(i).ToString()
    
        ' Create the new heading item, trimming the leading
        ' and trailing spaces.
        Dim heading As New HeadingInfo(itemText.Trim())
        heading.Index = i
    
        ' Categorize the headings by level. The code 
        ' recognizes only level 1 and level 2 headings, 
        ' but if you need the other levels, they are here.
        If String.CompareOrdinal(itemText, 0, spaces, 0, 8) = 0 Then
          ' Eight leading spaces? It is level 5.
          heading.Level = 5
        ElseIf String.CompareOrdinal(itemText, 0, spaces, 0, 6) = 0 Then
          ' Six leading spaces? It is level 4.
          heading.Level = 4
        ElseIf String.CompareOrdinal(itemText, 0, spaces, 0, 4) = 0 Then
          ' Four leading spaces? It is level 3.
          heading.Level = 3
        ElseIf String.CompareOrdinal(itemText, 0, spaces, 0, 2) = 0 Then
          ' Two leading spaces? It is level 2.
          heading.Level = 2
          level2Headings.Add(heading)
        Else
          heading.Level = 1
          level1Headings.Add(heading)
        End If
    
        allHeadings.Add(heading)
      Next i
    End Sub
    
    private static void GetHeadings()
    {
      string spaces = new string(' ', 8);
    
      //  Get all the headings in the current document.
      Word.Document doc = Application.ActiveDocument;
      object crossRefType = Word.WdReferenceType.wdRefTypeHeading;
      object headings = doc.GetCrossReferenceItems(ref crossRefType);
    
      //  Convert the variant array into a .NET Array.
      Array items = ((Array)(headings));
    
      //  Loop through all the items in the array. They are
      //  numbered using a 1-based index, because
      //  the array came from VBA.
      for (int i = items.GetLowerBound(0); 
        i <= items.GetUpperBound(0); i++)
      {
        //  Get the text from the array.
        string itemText = items.GetValue(i).ToString();
    
        //  Create the new heading item, trimming the leading
        //  and trailing spaces.
        HeadingInfo heading = new HeadingInfo(itemText.Trim());
        heading.Index = i;
    
        //  Categorize the headings by level. The code 
        //  recognizes only level 1 and level 2 headings, 
        //  but if you need the other levels, they are here.
        if (string.CompareOrdinal(itemText, 0, spaces, 0, 8) == 0)
        {
          //  Eight leading spaces? It is level 5.
          heading.Level = 5;
        }
        else if (string.CompareOrdinal(itemText, 0, spaces, 0, 6) == 0)
        {
          //  Six leading spaces? It is level 4.
          heading.Level = 4;
        }
        else if (string.CompareOrdinal(itemText, 0, spaces, 0, 4) == 0)
        {
          //  Four leading spaces? It is level 3.
          heading.Level = 3;
        }
        else if (string.CompareOrdinal(itemText, 0, spaces, 0, 2) == 0)
        {
          //  Two leading spaces? It is level 2.
          heading.Level = 2;
          level2Headings.Add(heading);
        }
        else
        {
          heading.Level = 1;
          level1Headings.Add(heading);
        }
    
        allHeadings.Add(heading);
      }
    }
    
  7. The add-in must be able to create a single string that contains all the level 2 headings, separated with a line break. To support this behavior, add the following procedure to the DocToPPT class.

    This procedure loops through each item in the list of headings, adds each to an array of strings, and calls the String.Join method to create the output string.

    Private Shared Function BuildAgendaList( _
     ByVal headings As List(Of HeadingInfo)) As String
    
      ' Loop through all the items and
      ' return an agenda list.
    
      ' Create an array of strings.
      Dim items(headings.Count - 1) As String
    
      ' Copy the items into the array of strings.
      For i As Integer = 0 To headings.Count - 1
        items(i) = headings(i).Text
      Next
    
      ' Concatenate the items, with a CR/LF between
      ' each item.
      Return String.Join(Environment.NewLine, items)
    End Function
    
    private static string BuildAgendaList(List<HeadingInfo> headings)
    {
      //  Loop through all the items and
      //  return an agenda list.
    
      //  Create an array of strings.
      string[] items = new string[headings.Count];
    
      //  Copy the items into the array of strings.
      for (int i = 0; i < headings.Count; i++)
      {
        items[i] = headings[i].Text;
      }
    
      //  Concatenate the items, with a CR/LF between
      //  each item.
      return string.Join(Environment.NewLine, items);
    }
    
  8. In the DocToPPT class, add the following two procedures.

    These two overloaded procedures simplify the task of adding a new slide to the presentation. This code lets you specify the presentation, the title, and the layout of the slide. The code then adds a new slide to the end of the presentation, sets its title, and returns a reference to the new slide.

    Private Shared Function AddSlide( _
     ByVal presentation As PowerPoint.Presentation, _
     ByVal title As String) As PowerPoint.Slide
    
      Return AddSlide(presentation, title, _
       PowerPoint.PpSlideLayout.ppLayoutText)
    End Function
    
    Private Shared Function AddSlide( _
     ByVal presentation As PowerPoint.Presentation, _
     ByVal title As String, _
     ByVal layout As PowerPoint.PpSlideLayout) As PowerPoint.Slide
    
      ' Add a new slide at the end of the deck, and set its title.
      Dim slide As PowerPoint.Slide = presentation.Slides.Add( _
       presentation.Slides.Count + 1, layout)
      slide.Shapes(1).TextFrame.TextRange.Text = title
      Return slide
    End Function
    
    private static PowerPoint.Slide AddSlide(
      PowerPoint.Presentation presentation, string title)
    {
      return AddSlide(presentation, title,
        PowerPoint.PpSlideLayout.ppLayoutText);
    }
    
    private static PowerPoint.Slide AddSlide(
      PowerPoint.Presentation presentation, string title,
      PowerPoint.PpSlideLayout layout)
    {
      //  Add a new slide at the end of the deck, and set its title.
      PowerPoint.Slide slide = presentation.Slides.Add(
        presentation.Slides.Count + 1, layout);
      slide.Shapes[1].TextFrame.TextRange.Text = title;
      return slide;
    }
    
  9. In the DocToPPT class, add the following procedure.

    This procedure takes as parameters a reference to a PowerPoint presentation and a list of level 1 headings. The code creates a new title slide at the end of the current presentation, setting its text appropriately.

    Private Shared Sub AddTitleSlide( _
     ByVal presentation As PowerPoint.Presentation)
    
      Dim title As String
      ' There should be a level 1 heading, but if there is not,
      ' specify a title for the presentation.
      If level1Headings.Count > 0 Then
        title = level1Headings(0).Text
      Else
        title = "Presentation Title"
      End If
      AddSlide(presentation, title, _
       PowerPoint.PpSlideLayout.ppLayoutTitle)
    End Sub
    
    private static void AddTitleSlide(
      PowerPoint.Presentation presentation)
    {
      String title = String.Empty;
    
      //  There should be a level 1 heading, but if there is not,
      //  specify a title for the presentation.
      if (level1Headings.Count > 0)
      {
        title = level1Headings[0].Text;
      }
      else
      {
        title = "Presentation Title";
      }
    
      AddSlide(presentation, title, 
        PowerPoint.PpSlideLayout.ppLayoutTitle);
    }
    
  10. The add-in inserts an Agenda slide between each set of subtopics, delimited with level 2 headings in the document. On each Agenda slide, the add-in highlights the current topic and shades or dims all previous topics. To add this behavior, insert the following procedure into the DocToPPT class.

    This procedure adds a new slide to the end of the presentation with the correct title, inserts the agenda text into the second shape on the slide, and highlights the paragraphs appropriately.

    Private Shared Sub AddAgendaSlide( _
     ByVal presentation As PowerPoint.Presentation, _
     ByVal agendaText As String, _
     ByVal itemIndex As Integer)
    
      Dim slide As PowerPoint.Slide = _
       AddSlide(presentation, "Agenda")
    
      Dim range As PowerPoint.TextRange = _
       slide.Shapes(2).TextFrame.TextRange
      range.Text = agendaText
    
      ' Set all the topics you already covered to 
      ' a shadowed color. Remember that PowerPoint
      ' numbers its items using a 1-based index.
      For i As Integer = 1 To itemIndex - 1
        range.Paragraphs(i).Font.Color.SchemeColor = _
         PowerPoint.PpColorSchemeIndex.ppShadow
      Next i
    
      ' Set up the color and attributes for the current 
      ' agenda item.
      Dim fnt As PowerPoint.Font = range.Paragraphs(itemIndex).Font
      fnt.Color.SchemeColor = PowerPoint.PpColorSchemeIndex.ppTitle
      fnt.Bold = Office.MsoTriState.msoTrue
      fnt.Underline = Office.MsoTriState.msoTrue
    End Sub
    
    private static void AddAgendaSlide(
      PowerPoint.Presentation presentation, 
      string agendaText, int itemIndex)
    {
    
      PowerPoint.Slide slide = AddSlide(presentation, "Agenda");
      PowerPoint.TextRange range = 
        slide.Shapes[2].TextFrame.TextRange;
      range.Text = agendaText;
    
      //  Set all the topics you already covered to 
      //  a shadowed color. Remember that PowerPoint
      //  numbers its items using a 1-based index.
      for (int i = 1; i < itemIndex; i++)
      {
        range.Paragraphs(i, 1).Font.Color.SchemeColor = 
          PowerPoint.PpColorSchemeIndex.ppShadow;
      }
    
      //  Set up the color and attributes for the current 
      //  agenda item.
      PowerPoint.Font fnt = range.Paragraphs(itemIndex, 1).Font;
      fnt.Color.SchemeColor = PowerPoint.PpColorSchemeIndex.ppTitle;
      fnt.Bold = Office.MsoTriState.msoTrue;
      fnt.Underline = Office.MsoTriState.msoTrue;
    }
    
  11. Between Agenda slides, the add-in must insert one slide for each heading, looping until either it runs out of headings, or until it encounters another level 2 heading. When that happens, another Agenda slide is inserted. To add this behavior, insert the following procedure into the DocToPPT class.

    Private Shared Sub AddDetailSlide( _
     ByVal presentation As PowerPoint.Presentation, _
     ByVal item As Integer)
    
      ' The item parameter is a 1-based index, but the 
      ' level2Headings list is a 0-based collection.
      Dim heading As HeadingInfo = level2Headings(item - 1)
      AddSlide(presentation, heading.Text)
    
      ' Move to the heading after the current one.
      Dim index As Integer = heading.Index + 1
    
      ' Loop through headings until you hit another level 2 heading.
      ' For each, add a new slide.
      While index <= allHeadings.Count AndAlso _
       allHeadings(index - 1).Level <> 2
        AddSlide(presentation, _
        allHeadings(index - 1).Text)
        index += 1
      End While
    
    End Sub
    
    private static void AddDetailSlide(
      PowerPoint.Presentation presentation, int item)
    {
      //  The item parameter is a 1-based index, but the 
      //  level2Headings list is a 0-based collection.
      HeadingInfo heading = level2Headings[item - 1];
      AddSlide(presentation, heading.Text);
    
      //  Move to the heading after the current one.
      int index = heading.Index + 1;
    
      //  Loop through headings until you hit another level 2 heading.
      //  For each, add a new slide.
      while (index <= allHeadings.Count && 
        allHeadings[index - 1].Level != 2)
      {
        AddSlide(presentation, allHeadings[index - 1].Text);
        index += 1;
      }
    }
    
  12. Finally, add the following procedure to the DocToPPT class.

    This procedure is the main entry point for creating the presentation. It sets up all the necessary variables and references, creates a new instance of PowerPoint 2007, loops through all the level 2 headings, and creates Agenda and detail slides. Finally, the code displays the new presentation in an instance of PowerPoint 2007, so you can modify the presentation and save it manually.

    Public Shared Sub CreatePresentation()
      Dim ppt As PowerPoint.Application = Nothing
    
      Try
        allHeadings = New List(Of HeadingInfo)
        level1Headings = New List(Of HeadingInfo)
        level2Headings = New List(Of HeadingInfo)
        GetHeadings()
    
        ' The agenda information is fixed. It is a list
        ' of all the level 2 headings, as a series
        ' of paragraphs (one heading per paragraph).
        Dim agendaText As String = BuildAgendaList(level2Headings)
    
        ' Create a new instance of PowerPoint,
        ' and create a new presentation.
        ppt = New PowerPoint.Application
        Dim presentation As PowerPoint.Presentation = _
         ppt.Presentations.Add(Office.MsoTriState.msoTrue)
    
        ' Add the title slide.
        AddTitleSlide(presentation)
    
        ' Add agenda slides, and then add the slides between agenda slides,
        ' until you handle all the slides. There is
        ' one agenda topic for each level 2 heading, and
        ' the code inserts a copy of the Agenda slide for 
        ' each level 2 heading, highlighting the current topic.
        For i As Integer = 1 To level2Headings.Count
          AddAgendaSlide(presentation, agendaText, i)
          ' Add the rest of the slides for this agenda item.
          AddDetailSlide(presentation, i)
        Next i
    
      Catch ex As Exception
        MessageBox.Show(ex.Message)
    
      Finally
        ' Show the PowerPoint main window.
        If ppt IsNot Nothing Then
          ppt.Visible = Office.MsoTriState.msoTrue
          ppt.Activate()
          ppt = Nothing
        End If
      End Try
    End Sub
    
    public static void CreatePresentation()
    {
      PowerPoint.Application ppt = null;
    
      try
      {
        allHeadings = new List<HeadingInfo>();
        level1Headings = new List<HeadingInfo>();
        level2Headings = new List<HeadingInfo>();
        GetHeadings();
    
        //  The agenda information is fixed. It is a list
        //  of all the level 2 headings, as a series
        //  of paragraphs (one heading per paragraph).
        string agendaText = BuildAgendaList(level2Headings);
    
        //  Create a new instance of PowerPoint,
        //  and create a new presentation.
        ppt = new PowerPoint.Application();
        PowerPoint.Presentation presentation =
          ppt.Presentations.Add(Office.MsoTriState.msoTrue);
    
        //  Add the title slide.
        AddTitleSlide(presentation);
    
        //  Add agenda slides, and add the slides between agenda slides,
        //  until you handle all the slides. There is
        //  one agenda topic for each level 2 heading, and
        //  the code inserts a copy of the Agenda slide for 
        //  each level 2 heading, highlighting the current topic.
        for (int i = 1; i <= level2Headings.Count; i++)
        {
          AddAgendaSlide(presentation, agendaText, i);
          //  Add the rest of the slides for this agenda item.
          AddDetailSlide(presentation, i);
        }
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message);
      }
      finally
      {
        //  Show  the PowerPoint main window.
        if (ppt != null)
        {
          ppt.Visible = Office.MsoTriState.msoTrue;
          ppt.Activate();
          ppt = null;
        }
      }
    }
    
  13. To complete the add-in, in the Ribbon1 class, modify the OnClick event handler that you created earlier. Add the following code to the procedure, which calls the CreatePresentation method.

    DocToPPT.CreatePresentation()
    
    DocToPPT.CreatePresentation();
    
  14. Save the project.

Load a document that contains a combination of styles, including Heading 1 and Heading 2. Click the Add-Ins tab, and then click the new Create PPT button that the add-in placed in the Visual How-To group on the Office Fluent Ribbon. This action creates a new PowerPoint 2007 presentation based on the headings in the current Word 2007 document. Try modifying the theme. The colors on the Agenda slides update to match the current theme.

Read It

Creating this add-in introduces several issues in dealing with the PowerPoint 2007 object model. This Office Visual How-to article describes the following tasks.

  • Creating a new PowerPoint 2007 presentation from a Word 2007 document.

  • Retrieving the headings from a Word 2007 document.

  • Adding a new slide to a presentation and specifying the layout for the slide.

  • Adding an "Agenda" slide between each set of level 2 headings.

  • Modifying the style of text, including using theme colors.

As you might imagine, the PowerPoint 2007 object model is far richer than this one simple add-in can demonstrate. To interact with the PowerPoint object model in code, investigate the documentation in Explore It.

Explore It