Reordering Slides in PowerPoint 2010 Presentations

Office Visual How To

Summary: Use the strongly typed classes in the Open XML SDK 2.0 for Microsoft Office to reorder slides in a Microsoft PowerPoint 2010 document given the old and new positions, without loading the document into PowerPoint.

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

Published:   October 2010

Provided by:   Ken Getz, MCW Technologies

Overview

The Open XML file formats make it possible to reorder slides in Microsoft PowerPoint 2010 or PowerPoint 2007 documents, but doing this requires some effort. The Open XML SDK 2.0 adds strongly typed classes that simplify access to the Open XML file formats—the SDK simplifies the task of reordering slides. The code sample that is included with this Visual How To shows how to use the SDK to achieve this goal.

Code It

The sample provided with this Visual How To includes the code that is needed to reorder slides, given the original and new positions, in a PowerPoint 2010 or PowerPoint 2007 document. The following sections discuss the code in detail.

Setting Up References

To use the code from the Open XML SDK 2.0, you must add several references to your project. The sample project already includes these references. However, in your own code, you would have to explicitly reference the following assemblies:

  • WindowsBase—This reference may already be set for you, depending on the type of project that you create.

  • DocumentFormat.OpenXml—Installed by the Open XML SDK 2.0.

In addition, you should add the following using/Imports statements to the top of your code file.

Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Presentation
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;

Examining the Procedure

The PPTReorderSlides procedure accepts three parameters, which indicate the name of the presentation to modify (string), the original position of the slide that you want to move, and the new position where you want the slide to end up. The sample procedure includes some heuristics to determine how to handle specific cases:

  • To indicate that you want to use the final slide as the original or new position, pass a value less than 0 for the corresponding parameter. (In other words, passing a value of -1 for the original position will cause the procedure to move the final slide in the presentation to a new location.)

  • If the original position is larger than the number of slides in the presentation, the procedure moves the final slide in the deck to the new position.

  • If the new position is larger than the number of slides in the presentation, the procedure moves the selected slide to the final position in the presentation.

The procedure returns a value indicating its results:

  • If the original position and the new position are the same, the procedure does nothing at all and returns -1.

  • If the procedure moves a slide, it returns the new position of the specified slide.

The procedure declaration looks like the following:

Public Function PPTReorderSlides(ByVal fileName As String, _
  ByVal originalPosition As Integer, 
  ByVal newPosition As Integer) As Integer
public static int PPTReorderSlides(
  string fileName, int originalPosition, int newPosition)

The procedure modifies the presentation that you specify, moving a single slide from originalPosition to newPosition. To call the procedure, pass the parameter values, as shown in the example code. Be sure that you provide a document named C:\temp\Sample.pptx—which (for demonstration purposes) contains at least a few slides—before you run the sample code. The following code shows how to move the slide in position 0 to position 3.

Console.WriteLine(
  PPTReorderSlides("C:\temp\sample.pptx", 0, 3).ToString())
Console.WriteLine(
  PPTReorderSlides("C:\temp\sample.pptx", 0, 3).ToString());

The PPTReorderSlides function returns the position at which the slide ends up, which may differ from the requested new position, depending on the value for newPosition and the number of slides in the presentation. If the function does not move the slide, it returns -1.

Setting Up the Return Value

The sample procedure starts by setting up a return value, and confirming that the new and original positions are not identical. If they are, the code returns immediately.

' Assume that no slide moves; return -1.
Dim returnValue As Integer = -1

' Moving to and from same position? Get out now.
If newPosition = originalPosition Then
  Return returnValue
End If
// Assume that no slide moves; return -1.
int returnValue = -1;

// Moving to and from same position? Get out now.
if (newPosition == originalPosition)
{
  return returnValue;
}

Accessing the Presentation

The code next opens the document, using the PresentationDocument.Open method and indicating that the document should be open for read/write permission (the final True parameter). The code immediately retrieves a reference to the presentation authors part and, if the reference is null, throws an exception (if the code cannot find the presentation part, something is wrong with the presentation).

Using doc As PresentationDocument = 
  PresentationDocument.Open(fileName, True)

  ' Get the presentation part of the document.
  Dim presentationPart As PresentationPart = doc.PresentationPart
  ' No presentation part? Something is wrong with the document.
  If presentationPart Is Nothing Then
    Throw New ArgumentException("fileName")
  End If
  ' Code removed here…
End Using
using (PresentationDocument doc = 
  PresentationDocument.Open(fileName, true))
{
  // Get the presentation part of the document.
  PresentationPart presentationPart = doc.PresentationPart;
  // No presentation part? Something is wrong with the document.
  if (presentationPart == null)
  {
    throw new ArgumentException("fileName");
  }
  // Code removed here…
}

Working with Positions

To move the slide from its current position to a new position, the procedure must confirm and possibly adjust the two numeric parameters. The code first retrieves the number of slides in the presentation and stores the value into a variable. If the slide count is 0, there is no reason to continue, and the procedure returns. Given the slide count, the procedure subtracts 1 to calculate the maximum position, and then calls the CalcPositions procedure to adjust the original and new positions, as required. The CalcPositions procedure checks for negative values, and positions outside the range of available slides. Given references to the originalPosition and newPosition values, and the maximum position value, the CalcPosition procedure adjusts the values, as necessary.

Private Sub CalcPositions(
  ByRef originalPosition As Integer,
  ByRef newPosition As Integer, ByVal maxPosition As Integer)

  ' Adjust the original and new slide position, as necessary.

  If originalPosition < 0 Then
    ' Ask for the slide in the final position? Get that value now.
    originalPosition = maxPosition
  End If

  If newPosition < 0 Then
    ' Ask for the final position? Get that value now.
    newPosition = maxPosition
  End If

  If originalPosition > maxPosition Then
    originalPosition = maxPosition
  End If
  If newPosition > maxPosition Then
    newPosition = maxPosition
  End If
End Sub
private static void CalcPositions(
  ref int originalPosition, ref int newPosition, int maxPosition)
{
  // Adjust the original and new slide position, as necessary.
  if (originalPosition < 0)
  {
    // Ask for the slide in the final position? Get that value now.
    originalPosition = maxPosition;
  }

  if (newPosition < 0)
  {
    // Ask for the final position? Get that value now.
    newPosition = maxPosition;
  }

  if (originalPosition > maxPosition)
  {
    originalPosition = maxPosition;
  }
  if (newPosition > maxPosition)
  {
    newPosition = maxPosition;
  }
}

The PPTReorderSlides procedure includes the following code that sets up and calls the CalcPositions procedure.

' If you are here, you know that presentationPart exists.
Dim slideCount As Integer = presentationPart.SlideParts.Count()

' No slides? Just return -1 indicating that nothing happened.
If slideCount = 0 Then
  Return returnValue
End If

' There are slides. Calculate real positions.
Dim maxPosition As Integer = slideCount - 1

' Adjust the positions, if necessary.
CalcPositions(originalPosition, newPosition, maxPosition)
// If you are here, you know that presentationPart exists.
int slideCount = presentationPart.SlideParts.Count();

// No slides? Just return -1 indicating that nothing happened.
// Original and new positions the same? Nothing to do.
if (slideCount == 0)
{
  return returnValue;
}
// There are slides. Calculate real positions.
int maxPosition = slideCount - 1;
// Adjust the positions, if necessary.
CalcPositions(ref originalPosition, ref newPosition, maxPosition);

Performing the Reordering

Once the code has adjusted the original and new positions, the sample code can actually perform the reordering. Of course, if the old and new positions are the same, there is nothing to do, and the code just returns.

  If newPosition <> originalPosition Then
    ' Code removed here…
  End If
End Using
Return returnValue
  if (newPosition != originalPosition)
  {
    // Code removed here…
  }
}
return returnValue;

On the other hand, given distinct new and original values, the code starts by retrieving a reference to the presentation contents, and then the slide ID list within the presentation.

Dim presentation As Presentation = presentationPart.Presentation
Dim slideIdList As SlideIdList = presentation.SlideIdList
Presentation presentation = presentationPart.Presentation;
SlideIdList slideIdList = presentation.SlideIdList;

Next, the code retrieves the necessary slide ID for both the source and target slide (the target slide currently appears at the new position).

Dim sourceSlide As SlideId =
  CType(slideIdList.ChildElements(originalPosition), SlideId)
Dim targetSlide As SlideId =
  CType(slideIdList.ChildElements(newPosition), SlideId)
SlideId sourceSlide = 
  (SlideId)(slideIdList.ChildElements[originalPosition]);
SlideId targetSlide = 
  (SlideId)(slideIdList.ChildElements[newPosition]);

The next step is somewhat tricky: The procedure must move the original slide into its new position, but the code cannot move a slide while it is part of an XML node tree. Therefore, the code must remove the slide from its XML tree before it tries to move it.

sourceSlide.Remove()
sourceSlide.Remove();

Given a free-floating slide, the code can easily place the original slide at its new position. If the new position is greater than the original position, the code inserts the original slide after the target slide. If the new position is less than the original position, the code inserts the original slide before the target slide. Either way, the code sets the return value and saves the presentation:

If newPosition > originalPosition Then
  slideIdList.InsertAfter(sourceSlide, targetSlide)
Else
  slideIdList.InsertBefore(sourceSlide, targetSlide)
End If

' Set the return value.
returnValue = newPosition

' Save the modified presentation.
presentation.Save()
if (newPosition > originalPosition)
{
  slideIdList.InsertAfter(sourceSlide, targetSlide);
}
else
{
  slideIdList.InsertBefore(sourceSlide, targetSlide);
}

// Set the return value.
returnValue = newPosition;

// Save the modified presentation.
presentation.Save();

Sample Procedure

The following code shows the full sample procedure.

Public Function PPTReorderSlides(ByVal fileName As String, _
  ByVal originalPosition As Integer, 
  ByVal newPosition As Integer) As Integer

  ' Assume that no slide moves; return -1.
  Dim returnValue As Integer = -1

  ' Moving to and from same position? Get out now.
  If newPosition = originalPosition Then
    Return returnValue
  End If

  Using doc As PresentationDocument = 
    PresentationDocument.Open(fileName, True)
    ' Get the presentation part of the document.
    Dim presentationPart As PresentationPart = doc.PresentationPart
    ' No presentation part? Something is wrong with the document.
    If presentationPart Is Nothing Then
      Throw New ArgumentException("fileName")
    End If

    ' If you are here, you know that presentationPart exists.
    Dim slideCount As Integer = presentationPart.SlideParts.Count()
     ' No slides? Just return -1 indicating that nothing happened.
    If slideCount = 0 Then
      Return returnValue
    End If

    ' There are slides. Calculate real positions.
    Dim maxPosition As Integer = slideCount - 1

    ' Adjust the positions, if necessary.
    CalcPositions(originalPosition, newPosition, maxPosition)

    ' The two positions could have ended up being the same 
    ' thing. There is nothing to do, in that case. Otherwise,
    ' do the work.
    If newPosition <> originalPosition Then
      Dim presentation As Presentation = presentationPart.Presentation
      Dim slideIdList As SlideIdList = presentation.SlideIdList

      ' Get the slide ID of the source and target slides.
      Dim sourceSlide As SlideId =
        CType(slideIdList.ChildElements(originalPosition), SlideId)
      Dim targetSlide As SlideId =
        CType(slideIdList.ChildElements(newPosition), SlideId)

      ' Remove the source slide from its parent tree. You cannot
      ' move a slide while it is part of an XML node tree.
      sourceSlide.Remove()

      If newPosition > originalPosition Then
        slideIdList.InsertAfter(sourceSlide, targetSlide)
      Else
        slideIdList.InsertBefore(sourceSlide, targetSlide)
      End If

      ' Set the return value.
      returnValue = newPosition

      ' Save the modified presentation.
      presentation.Save()
    End If
  End Using
  Return returnValue
End Function

Private Sub CalcPositions(
  ByRef originalPosition As Integer,
  ByRef newPosition As Integer, ByVal maxPosition As Integer)

  ' Adjust the original and new slide position, as necessary.

  If originalPosition < 0 Then
    ' Ask for the slide in the final position? Get that value now.
    originalPosition = maxPosition
  End If

  If newPosition < 0 Then
    ' Ask for the final position? Get that value now.
    newPosition = maxPosition
  End If

  If originalPosition > maxPosition Then
    originalPosition = maxPosition
  End If
  If newPosition > maxPosition Then
    newPosition = maxPosition
  End If
End Sub
public static int PPTReorderSlides(string fileName, int originalPosition, int newPosition)
{
  // Assume that no slide moves; return -1.
  int returnValue = -1;

  // Moving to and from same position? Get out now.
  if (newPosition == originalPosition)
  {
    return returnValue;
  }

  using (PresentationDocument doc = 
    PresentationDocument.Open(fileName, true))
  {
    // Get the presentation part of the document.
    PresentationPart presentationPart = doc.PresentationPart;
    // No presentation part? Something is wrong with the document.
    if (presentationPart == null)
    {
      throw new ArgumentException("fileName");
    }

    // If you are here, you know that presentationPart exists.
    int slideCount = presentationPart.SlideParts.Count();

    // No slides? Just return -1 indicating that nothing happened.
    if (slideCount == 0)
    {
      return returnValue;
    }

    // There are slides. Calculate real positions.
    int maxPosition = slideCount - 1;

    // Adjust the positions, if necessary.
    CalcPositions(ref originalPosition, ref newPosition, maxPosition);

    // The two positions could have ended up being the same 
    // thing. There is nothing to do, in that case. Otherwise,
    // do the work.
    if (newPosition != originalPosition)
    {
      Presentation presentation = presentationPart.Presentation;
      SlideIdList slideIdList = presentation.SlideIdList;

      // Get the slide ID of the source and target slides.
      SlideId sourceSlide = 
        (SlideId)(slideIdList.ChildElements[originalPosition]);
      SlideId targetSlide = 
        (SlideId)(slideIdList.ChildElements[newPosition]);

      // Remove the source slide from its parent tree. You cannot
      // move a slide while it is part of an XML node tree.
      sourceSlide.Remove();

      if (newPosition > originalPosition)
      {
        slideIdList.InsertAfter(sourceSlide, targetSlide);
      }
      else
      {
        slideIdList.InsertBefore(sourceSlide, targetSlide);
      }

      // Set the return value.
      returnValue = newPosition;

      // Save the modified presentation.
      presentation.Save();
    }
  }
  return returnValue;
}

private static void CalcPositions(
  ref int originalPosition, ref int newPosition, int maxPosition)
{
  // Adjust the original and new slide position, as necessary.
  if (originalPosition < 0)
  {
    // Ask for the slide in the final position? Get that value now.
    originalPosition = maxPosition;
  }

  if (newPosition < 0)
  {
    // Ask for the final position? Get that value now.
    newPosition = maxPosition;
  }

  if (originalPosition > maxPosition)
  {
    originalPosition = maxPosition;
  }
  if (newPosition > maxPosition)
  {
    newPosition = maxPosition;
  }
}
Read It

The sample that is included with this Visual How To demonstrates code that reorders slides in a PowerPoint presentation. To use the sample, you must install the Open XML SDK 2.0, available from the link listed in the Explore It section. The sample also uses a modified version of code included as part of a set of code examples for the Open XML SDK 2.0. The Explore It section also includes a link to the full set of code examples, although you can use the sample without downloading and installing the examples.

The sample application demonstrates only some the available properties and methods that are provided by the Open XML SDK 2.0 that you can interact with when modifying a presentation's structure. For more information, see the documentation that is included with the Open XML SDK 2.0 Productivity Tool (click the Open XML SDK Documentation tab in the lower-left corner of the application window, and search for the class that you need to study). Although the documentation does not currently include code examples, given the sample shown here and the documentation, you should be able to successfully modify the sample application.

See It

Watch the video

> [!VIDEO https://www.microsoft.com/en-us/videoplayer/embed/3d4b29c3-ebdf-4609-83fd-544fa812ce93]

Length: 00:09:07

Click to grab code

Grab the Code

Explore It

About the Author
Ken Getz is a senior consultant with MCW Technologies. He is coauthor of ASP.NET Developers Jumpstart (Addison-Wesley, 2002), Access Developer's Handbook (Sybex, 2001), and VBA Developer's Handbook, 2nd Edition (Sybex, 2001).