如何:从演示文稿中删除幻灯片

上次修改时间: 2010年10月14日

适用范围: Excel 2010 | Office 2010 | PowerPoint 2010 | Word 2010

本文内容
获取 Presentation 对象
基本演示文稿文档结构
统计幻灯片的数目
删除特定幻灯片
示例代码

本主题演示如何使用 Open XML SDK 2.0 for Microsoft Office 以编程方式从演示文稿中删除幻灯片。它还演示如何从任何可能存在的自定义放映中删除对幻灯片的所有引用。若要删除演示文稿文件中的特定幻灯片,您首先需要知道演示文稿中幻灯片的数目。因此,本操作方法中的代码分为两部分。第一部分统计幻灯片数目,第二部分删除特定索引处的幻灯片。

备注

从更加复杂的演示文稿(如那些包含大纲视图设置的演示文稿)中删除幻灯片可能需要其他步骤(举例来说)。

编译本主题中的代码需要使用以下程序集指令。

using System;
using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Packaging;
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports DocumentFormat.OpenXml.Presentation
Imports DocumentFormat.OpenXml.Packaging

获取 Presentation 对象

在 Open XML SDK 中,PresentationDocument 类表示演示文稿文档包。若要处理演示文稿文档,请首先创建 PresentationDocument 类的实例,然后处理该实例。若要从文档中创建类实例,请调用 Open 方法重载之一。本主题中的代码使用 PresentationDocument.Open(String, Boolean) 方法,它将文件路径作为第一个参数以指定要打开的文件,并将布尔值作为第二个参数以指定文档是否可编辑。将此第二个参数设置为 false 将打开文件进行只读访问。如果希望打开文件进行读/写访问,请将其设置为 true。本主题的中代码打开文件两次,一次用来统计幻灯片的数目,一次用来删除特定幻灯片。统计演示文稿中幻灯片的数目时,最好打开文件进行只读访问,以避免对文件进行意外写入。以下 using 语句打开文件进行只读访问。在此代码示例中,presentationFile 参数是一个字符串,表示要从中打开文档的文件路径。

// Open the presentation as read-only.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
{
    // Insert other code here.
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
' Open the presentation as read-only.
Using presentationDocument As PresentationDocument = PresentationDocument.Open(presentationFile, False)
    ' Insert other code here.
End Using

若要从演示文稿文件中删除幻灯片,请打开文件进行读/写访问,如以下的 using 语句所示。

// Open the source document as read/write.
using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
{
    // Place other code here.
}
' Open the source document as read/write.
Using presentationDocument As PresentationDocument = PresentationDocument.Open(presentationFile, True)
    ' Place other code here.
End Using

using 语句提供典型 .Open, .Save, .Close 序列的建议备选序列。它确保在遇到右大括号时会自动调用 Dispose 方法(Open XML SDK 用来清理资源的内部方法)。using 语句后面的块为 using 语句中创建或指定的对象设定范围,在此示例中这个范围就是 presentationDocument。

基本演示文稿文档结构

PresentationML 文档的基本文档结构由包含演示文稿定义的主部件组成。ISO/IEC 29500(该链接可能指向英文页面) 规范中的以下文本介绍了 PresentationML 包的整体形式。

PresentationML 包的主部件以演示文稿根元素开头。该元素包含演示文稿,演示文稿又引用幻灯片 列表、幻灯片母版 列表、备注母版 列表和讲义母版 列表。幻灯片列表指的是演示文稿中的所有幻灯片;幻灯片母版列表指的是演示文稿中使用的全部幻灯片母版;备注母版包含有关备注页格式的信息;讲义母版描述讲义的外观。

讲义 是打印的一组幻灯片,可提供给访问群体 以供他们将来参考。

除了文本和图形,每个幻灯片还可以包含注释 和备注,可以具有布局,并且可以是一个或多个自定义演示文稿 的组成部分。(注释是供维护演示文稿幻灯片平台的人员参考的批注。备注是供演示者或访问群体参考的提醒信息或一段文字。)

PresentationML 文档可以包含的其他功能如下:动画、音频、视频 以及幻灯片之间的切换。

PresentationML 文档不会存储为单个部件中的一个大型正文。而实现某些功能组合的元素会存储在各个部件中。例如,文档中的所有注释都存储在一个注释部件中,而每个幻灯片都有自己的部件。

© ISO/IEC29500: 2008。

以下 XML 代码段表示包含用 ID 267 和 256 表示的两个幻灯片的演示文稿。

<p:presentation xmlns:p="…" … > 
   <p:sldMasterIdLst>
      <p:sldMasterId
         xmlns:rel="http://…/relationships" rel:id="rId1"/>
   </p:sldMasterIdLst>
   <p:notesMasterIdLst>
      <p:notesMasterId
         xmlns:rel="http://…/relationships" rel:id="rId4"/>
   </p:notesMasterIdLst>
   <p:handoutMasterIdLst>
      <p:handoutMasterId
         xmlns:rel="http://…/relationships" rel:id="rId5"/>
   </p:handoutMasterIdLst>
   <p:sldIdLst>
      <p:sldId id="267"
         xmlns:rel="http://…/relationships" rel:id="rId2"/>
      <p:sldId id="256"
         xmlns:rel="http://…/relationships" rel:id="rId3"/>
   </p:sldIdLst>
       <p:sldSz cx="9144000" cy="6858000"/>
   <p:notesSz cx="6858000" cy="9144000"/>
</p:presentation>

通过使用 Open XML SDK 2.0,您可以利用 PresentationML 元素所对应的强类型类创建文档结构和内容。可以在 DocumentFormat.OpenXml.Presentation 命名空间中找到这些类。下表列出了 sld、sldLayout、sldMaster 和 notesMaster 元素所对应类的类名称。

PresentationML 元素

Open XML SDK 2.0 类

说明

sld

Slide

演示文稿幻灯片。它是 SlidePart 的根元素。

sldLayout

SlideLayout

幻灯片版式。它是 SlideLayoutPart 的根元素。

sldMaster

SlideMaster

幻灯片母版。它是 SlideMasterPart 的根元素。

notesMaster

NotesMaster

备注母版(或讲义母版)。它是 NotesMasterPart 的根元素。

统计幻灯片的数目

示例代码由 CountSlides 方法的两个重载组成。第一个重载使用 string 参数,第二个重载使用 PresentationDocument 参数。在第一个 CountSlides 方法中,示例代码在 using 语句中打开演示文稿文档。然后它将 PresentationDocument 对象传递给第二个 CountSlides 方法,该方法返回一个整数,表示演示文稿中幻灯片的数目。

// Pass the presentation to the next CountSlides method
// and return the slide count.
return CountSlides(presentationDocument);
' Pass the presentation to the next CountSlides method
' and return the slide count.
Return CountSlides(presentationDocument)

在第二个 CountSlides 方法中,代码验证传入的 PresentationDocument 对象是否为 null,如果不为 null,则从 PresentationDocument 对象中获取 PresentationPart 对象。通过使用 SlideParts,代码获取并返回 slideCount。

// Check for a null document object.
if (presentationDocument == null)
{
    throw new ArgumentNullException("presentationDocument");
}

int slidesCount = 0;

// Get the presentation part of document.
PresentationPart presentationPart = presentationDocument.PresentationPart;

// Get the slide count from the SlideParts.
if (presentationPart != null)
{
    slidesCount = presentationPart.SlideParts.Count();
}
// Return the slide count to the previous method.
return slidesCount;
' Check for a null document object.
If presentationDocument Is Nothing Then
    Throw New ArgumentNullException("presentationDocument")
End If

Dim slidesCount As Integer = 0

' Get the presentation part of document.
Dim presentationPart As PresentationPart = presentationDocument.PresentationPart

' Get the slide count from the SlideParts.
If presentationPart IsNot Nothing Then
    slidesCount = presentationPart.SlideParts.Count()
End If
' Return the slide count to the previous method.
Return slidesCount

删除特定幻灯片

用于删除幻灯片的代码使用 DeleteSlide 方法的两个重载。第一个重载的 DeleteSlide 方法采用两个参数:一个表示演示文稿文件名和路径的字符串,和一个表示要删除的幻灯片从零开始的索引位置的整数。此方法将打开演示文稿文件进行读/写访问,获取 PresentationDocument 对象,然后将此对象和索引号传递给下一个执行删除操作的重载 DeleteSlide 方法。

// Get the presentation object and pass it to the next DeleteSlide method.
public static void DeleteSlide(string presentationFile, int slideIndex)
{
    // Open the source document as read/write.

    using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
    {
      // Pass the source document and the index of the slide to be deleted to the next DeleteSlide method.
      DeleteSlide(presentationDocument, slideIndex);
    }
}  
' Check for a null document object.
If presentationDocument Is Nothing Then
    Throw New ArgumentNullException("presentationDocument")
End If

Dim slidesCount As Integer = 0

' Get the presentation part of document.
Dim presentationPart As PresentationPart = presentationDocument.PresentationPart

' Get the slide count from the SlideParts.
If presentationPart IsNot Nothing Then
    slidesCount = presentationPart.SlideParts.Count()
End If
' Return the slide count to the previous method.
Return slidesCount

第二个重载的 DeleteSlide 方法的第一部分使用 CountSlides 方法获取演示文稿中的幻灯片数目。然后获取演示文稿中幻灯片 ID 的列表,标识幻灯片列表中的指定幻灯片,并从幻灯片列表中移除该幻灯片。

// Delete the specified slide from the presentation.
public static void DeleteSlide(PresentationDocument presentationDocument, int slideIndex)
{
    if (presentationDocument == null)
    {
        throw new ArgumentNullException("presentationDocument");
    }

    // Use the CountSlides sample to get the number of slides in the presentation.
    int slidesCount = CountSlides(presentationDocument);

    if (slideIndex < 0 || slideIndex >= slidesCount)
    {
        throw new ArgumentOutOfRangeException("slideIndex");
    }

    // Get the presentation part from the presentation document. 
    PresentationPart presentationPart = presentationDocument.PresentationPart;

    // Get the presentation from the presentation part.
    Presentation presentation = presentationPart.Presentation;

    // Get the list of slide IDs in the presentation.
    SlideIdList slideIdList = presentation.SlideIdList;

    // Get the slide ID of the specified slide
    SlideId slideId = slideIdList.ChildElements[slideIndex] as SlideId;

    // Get the relationship ID of the slide.
    string slideRelId = slideId.RelationshipId;

    // Remove the slide from the slide list.
    slideIdList.RemoveChild(slideId);
' Delete the specified slide from the presentation.
Public Shared Sub DeleteSlide(ByVal presentationDocument As 
    If presentationDocument Is Nothing Then
        Throw New ArgumentNullException("presentationDocument")
    End If

    ' Use the CountSlides sample to get the number of slides in the presentation.
    Dim slidesCount As Integer = CountSlides(presentationDocument)

    If slideIndex < 0 OrElse slideIndex >= slidesCount Then
        Throw New ArgumentOutOfRangeException("slideIndex")
    End If

    ' Get the presentation part from the presentation document. 
    Dim presentationPart As PresentationPart = presentationDocument.PresentationPart

    ' Get the presentation from the presentation part.
    Dim presentation As Presentation = presentationPart.Presentation

    ' Get the list of slide IDs in the presentation.
    Dim slideIdList As SlideIdList = presentation.SlideIdList

    ' Get the slide ID of the specified slide
    Dim slideId As SlideId = TryCast(slideIdList.ChildElements(slideIndex), SlideId)

    ' Get the relationship ID of the slide.
    Dim slideRelId As String = slideId.RelationshipId

    ' Remove the slide from the slide list.
    slideIdList.RemoveChild(slideId)

第二个重载的 DeleteSlide 方法的下一部分从自定义放映中移除对已删除幻灯片的所有引用。为此,它循环访问自定义放映列表并循环访问每个自定义放映中的幻灯片列表。然后它声明并实例化幻灯片列表项的链接列表,并使用已删除幻灯片的关系 ID 查找对该幻灯片的引用。它将这些引用添加到幻灯片列表项的列表中,然后从各自的自定义放映的幻灯片列表中移除每个这样的引用。

// Remove references to the slide from all custom shows.
if (presentation.CustomShowList != null)
{
    // Iterate through the list of custom shows.
    foreach (var customShow in presentation.CustomShowList.Elements<CustomShow>())
    {
        if (customShow.SlideList != null)
        {
            // Declare a link list of slide list entries.
            LinkedList<SlideListEntry> slideListEntries = new LinkedList<SlideListEntry>();
            foreach (SlideListEntry slideListEntry in customShow.SlideList.Elements())
            {
                // Find the slide reference to remove from the custom show.
                if (slideListEntry.Id != null && slideListEntry.Id == slideRelId)
                {
                    slideListEntries.AddLast(slideListEntry);
                }
            }

            // Remove all references to the slide from the custom show.
            foreach (SlideListEntry slideListEntry in slideListEntries)
            {
                customShow.SlideList.RemoveChild(slideListEntry);
            }
        }
    }
}
' Remove references to the slide from all custom shows.
If presentation.CustomShowList IsNot Nothing Then
    ' Iterate through the list of custom shows.
    For Each customShow In presentation.CustomShowList.Elements(Of CustomShow)()
        If customShow.SlideList IsNot Nothing Then
            ' Declare a link list of slide list entries.
            Dim slideListEntries As New LinkedList(Of SlideListEntry)()
            For Each slideListEntry As SlideListEntry In customShow.SlideList.Elements()
                ' Find the slide reference to remove from the custom show.
                If slideListEntry.Id IsNot Nothing AndAlso slideListEntry.Id = slideRelId Then
                    slideListEntries.AddLast(slideListEntry)
                End If
            Next slideListEntry

            ' Remove all references to the slide from the custom show.
            For Each slideListEntry As SlideListEntry In slideListEntries
                customShow.SlideList.RemoveChild(slideListEntry)
            Next slideListEntry
        End If
    Next customShow
End If

最后,代码保存修改的演示文稿,并删除已删除幻灯片的幻灯片部件。

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

// Get the slide part for the specified slide.
SlidePart slidePart = presentationPart.GetPartById(slideRelId) as SlidePart;

// Remove the slide part.
presentationPart.DeletePart(slidePart);
}
' Save the modified presentation.
presentation.Save()

' Get the slide part for the specified slide.
Dim slidePart As SlidePart = TryCast(presentationPart.GetPartById(slideRelId), SlidePart)

' Remove the slide part.
presentationPart.DeletePart(slidePart)
End Sub

示例代码

以下是两个重载的方法 CountSlides 和 DeleteSlide 的完整示例代码。若要使用该代码,可以使用以下调用作为示例来删除演示文稿文件"Myppt6.pptx"中位于索引 2 处的幻灯片。

DeleteSlide(@"C:\Users\Public\Documents\Myppt6.pptx", 2);
DeleteSlide("C:\Users\Public\Documents\Myppt6.pptx", 0)

您还可以使用以下调用统计演示文稿中幻灯片的数目。

Console.WriteLine("Number of slides = {0}",
CountSlides(@"C:\Users\Public\Documents\Myppt6.pptx"));
Console.WriteLine("Number of slides = {0}", _
CountSlides("C:\Users\Public\Documents\Myppt6.pptx"))

最好在执行删除前和执行删除后均统计幻灯片的数目。

以下是使用 C# 和 Visual Basic 编写的完整示例代码。

// Get the presentation object and pass it to the next CountSlides method.
public static int CountSlides(string presentationFile)
{
    // Open the presentation as read-only.
    using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
    {
        // Pass the presentation to the next CountSlide method
        // and return the slide count.
        return CountSlides(presentationDocument);
    }
}

// Count the slides in the presentation.
public static int CountSlides(PresentationDocument presentationDocument)
{
    // Check for a null document object.
    if (presentationDocument == null)
    {
        throw new ArgumentNullException("presentationDocument");
    }

    int slidesCount = 0;

    // Get the presentation part of document.
    PresentationPart presentationPart = presentationDocument.PresentationPart;

    // Get the slide count from the SlideParts.
    if (presentationPart != null)
    {
         slidesCount = presentationPart.SlideParts.Count();
     }

    // Return the slide count to the previous method.
    return slidesCount;
}
//
// Get the presentation object and pass it to the next DeleteSlide method.
public static void DeleteSlide(string presentationFile, int slideIndex)
{
    // Open the source document as read/write.

    using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
    {
      // Pass the source document and the index of the slide to be deleted to the next DeleteSlide method.
      DeleteSlide(presentationDocument, slideIndex);
    }
}  

// Delete the specified slide from the presentation.
public static void DeleteSlide(PresentationDocument presentationDocument, int slideIndex)
{
    if (presentationDocument == null)
    {
        throw new ArgumentNullException("presentationDocument");
    }

    // Use the CountSlides sample to get the number of slides in the presentation.
    int slidesCount = CountSlides(presentationDocument);

    if (slideIndex < 0 || slideIndex >= slidesCount)
    {
        throw new ArgumentOutOfRangeException("slideIndex");
    }

    // Get the presentation part from the presentation document. 
    PresentationPart presentationPart = presentationDocument.PresentationPart;

    // Get the presentation from the presentation part.
    Presentation presentation = presentationPart.Presentation;

    // Get the list of slide IDs in the presentation.
    SlideIdList slideIdList = presentation.SlideIdList;

    // Get the slide ID of the specified slide
    SlideId slideId = slideIdList.ChildElements[slideIndex] as SlideId;

    // Get the relationship ID of the slide.
    string slideRelId = slideId.RelationshipId;

    // Remove the slide from the slide list.
    slideIdList.RemoveChild(slideId);

//
    // Remove references to the slide from all custom shows.
    if (presentation.CustomShowList != null)
    {
        // Iterate through the list of custom shows.
        foreach (var customShow in presentation.CustomShowList.Elements<CustomShow>())
        {
            if (customShow.SlideList != null)
            {
                // Declare a link list of slide list entries.
                LinkedList<SlideListEntry> slideListEntries = new LinkedList<SlideListEntry>();
                foreach (SlideListEntry slideListEntry in customShow.SlideList.Elements())
                {
                    // Find the slide reference to remove from the custom show.
                    if (slideListEntry.Id != null && slideListEntry.Id == slideRelId)
                    {
                        slideListEntries.AddLast(slideListEntry);
                    }
                }

                // Remove all references to the slide from the custom show.
                foreach (SlideListEntry slideListEntry in slideListEntries)
                {
                    customShow.SlideList.RemoveChild(slideListEntry);
                }
            }
        }
    }

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

    // Get the slide part for the specified slide.
    SlidePart slidePart = presentationPart.GetPartById(slideRelId) as SlidePart;

    // Remove the slide part.
    presentationPart.DeletePart(slidePart);
}
' Count the number of slides in the presentation.
Public Function CountSlides(ByVal presentationFile As String) As Integer
    ' Open the presentation as read-only.
    Using presentationDocument__1 As PresentationDocument = PresentationDocument.Open(presentationFile, False)
        ' Pass the presentation to the next CountSlides method
        ' and return the slide count.
        Return CountSlides(presentationDocument__1)
    End Using
End Function
' Count the slides in the presentation.
Public Function CountSlides(ByVal presentationDocument As PresentationDocument) As Integer
    ' Check for a null document object.
    If presentationDocument Is Nothing Then
        Throw New ArgumentNullException("presentationDocument")
    End If

    Dim slidesCount As Integer = 0

    ' Get the presentation part of document.
    Dim presentationPart As PresentationPart = presentationDocument.PresentationPart

    If presentationPart IsNot Nothing AndAlso presentationPart.Presentation IsNot Nothing Then
        ' Get the Presentation object from the presentation part.
        Dim presentation As Presentation = presentationPart.Presentation

        ' Verify that the presentation contains slides. 
        If presentation.SlideIdList IsNot Nothing Then

            ' Get the slide count from the slide ID list. 
            slidesCount = presentation.SlideIdList.Elements(Of SlideId)().Count()
        End If
    End If

    ' Return the slide count to the previous method.
    Return slidesCount
End Function
' Delete the specified slide from the presentation.
Public Sub DeleteSlide(ByVal presentationFile As String, ByVal slideIndex As Integer)

    ' Open the source document as read/write.
    Dim presentationDocument As PresentationDocument = presentationDocument.Open(presentationFile, True)

    Using (presentationDocument)

        ' Pass the source document and the index of the slide to be deleted to the next DeleteSlide method.
        DeleteSlide2(presentationDocument, slideIndex)

    End Using

End Sub
' Delete the specified slide in the presentation.
Public Sub DeleteSlide2(ByVal presentationDocument As PresentationDocument, ByVal slideIndex As Integer)
    If (presentationDocument Is Nothing) Then
        Throw New ArgumentNullException("presentationDocument")
    End If

    ' Use the CountSlides code example to get the number of slides in the presentation.
    Dim slidesCount As Integer = CountSlides(presentationDocument)
    If ((slideIndex < 0) OrElse (slideIndex >= slidesCount)) Then
        Throw New ArgumentOutOfRangeException("slideIndex")
    End If

    ' Get the presentation part from the presentation document.
    Dim presentationPart As PresentationPart = presentationDocument.PresentationPart

    ' Get the presentation from the presentation part. 
    Dim presentation As Presentation = presentationPart.Presentation

    ' Get the list of slide IDs in the presentation.
    Dim slideIdList As SlideIdList = presentation.SlideIdList

    ' Get the slide ID of the specified slide.
    Dim slideId As SlideId = CType(slideIdList.ChildElements(slideIndex), SlideId)

    ' Get the relationship ID of the specified slide.
    Dim slideRelId As String = slideId.RelationshipId

    ' Remove the slide from the slide list.
    slideIdList.RemoveChild(slideId)
    ' Remove references to the slide from all custom shows.
    If (Not (presentation.CustomShowList) Is Nothing) Then

        ' Iterate through the list of custom shows.
        For Each customShow As System.Object In presentation.CustomShowList.Elements(Of  _
                               DocumentFormat.OpenXml.Presentation.CustomShow)()

            If (Not (customShow.SlideList) Is Nothing) Then

                ' Declare a linked list.
                Dim slideListEntries As LinkedList(Of SlideListEntry) = New LinkedList(Of SlideListEntry)

                ' Iterate through all the slides in the custom show.
                For Each slideListEntry As SlideListEntry In customShow.SlideList.Elements

                    ' Find the slide reference to be removed from the custom show.
                    If ((Not (slideListEntry.Id) Is Nothing) _
                                AndAlso (slideListEntry.Id = slideRelId)) Then

                        ' Add that slide reference to the end of the linked list.
                        slideListEntries.AddLast(slideListEntry)
                    End If
                Next

                ' Remove references to the slide from the custom show.
                For Each slideListEntry As SlideListEntry In slideListEntries
                    customShow.SlideList.RemoveChild(slideListEntry)
                Next
            End If
        Next
    End If

    ' Save the change to the presentation part.
    presentation.Save()

    ' Get the slide part for the specified slide.
    Dim slidePart As SlidePart = CType(presentationPart.GetPartById(slideRelId), SlidePart)

    ' Remove the slide part.
    presentationPart.DeletePart(slidePart)

End Sub

请参阅

引用

Class Library Reference