获取演示文稿中的所有幻灯片的标题

本主题演示如何使用 Open XML SDK for Office 中的类以编程方式获取演示文稿中所有幻灯片的标题。


获取 PresentationDocument 对象

在 Open XML SDK 中, PresentationDocument 类表示演示文稿文档包。 若要使用演示文稿文档,首先创建 PresentationDocument 类的实例,然后使用该实例。 若要从文档创建类实例,请调用 PresentationDocument.Open (String、Boolean) 使用文件路径的方法和布尔值作为指定文档是否可编辑的第二个参数。 若要打开只读文档,请为此参数指定值 false,如以下的 using 语句所示。 在该代码中, presentationFile 参数是一个字符串,表示要从中打开该文档的文件的路径。

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

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="https://…/relationships" rel:id="rId1"/>
       </p:sldMasterIdLst>
       <p:notesMasterIdLst>
          <p:notesMasterId
             xmlns:rel="https://…/relationships" rel:id="rId4"/>
       </p:notesMasterIdLst>
       <p:handoutMasterIdLst>
          <p:handoutMasterId
             xmlns:rel="https://…/relationships" rel:id="rId5"/>
       </p:handoutMasterIdLst>
       <p:sldIdLst>
          <p:sldId id="267"
             xmlns:rel="https://…/relationships" rel:id="rId2"/>
          <p:sldId id="256"
             xmlns:rel="https://…/relationships" rel:id="rId3"/>
       </p:sldIdLst>
           <p:sldSz cx="9144000" cy="6858000"/>
       <p:notesSz cx="6858000" cy="9144000"/>
    </p:presentation>

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

PresentationML 元素 Open XML SDK 类 说明
Sld Slide 演示文稿幻灯片。 它是 SlidePart 的根元素。
sldLayout SlideLayout 幻灯片版式。 它是 SlideLayoutPart 的根元素。
sldMaster SlideMaster 幻灯片母版。 它是 SlideMasterPart 的根元素。
notesMaster NotesMaster 备注母版(或讲义母版)。 它是 NotesMasterPart 的根元素。

示例代码

下面是可用于获取演示文稿文件中幻灯片标题的完整代码示例。 例如,可以在程序中使用以下 foreach 语句返回演示文稿文件"Myppt9.pptx"中的所有标题。

    foreach (string s in GetSlideTitles(@"C:\Users\Public\Documents\Myppt9.pptx"))
       Console.WriteLine(s);

结果将为表示演示文稿中的标题的字符串列表,每个字符串一行。

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


using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using D = DocumentFormat.OpenXml.Drawing;

GetSlideTitles(args[0]);

// Get a list of the titles of all the slides in the presentation.
static IList<string>? GetSlideTitles(string presentationFile)
{
    // Open the presentation as read-only.
    using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
    {
        return GetSlideTitlesFromPresentation(presentationDocument);
    }
}

// Get a list of the titles of all the slides in the presentation.
static IList<string>? GetSlideTitlesFromPresentation(PresentationDocument presentationDocument)
{
    // Get a PresentationPart object from the PresentationDocument object.
    PresentationPart? presentationPart = presentationDocument.PresentationPart;

    if (presentationPart is not null && presentationPart.Presentation is not null)
    {
        // Get a Presentation object from the PresentationPart object.
        Presentation presentation = presentationPart.Presentation;

        if (presentation.SlideIdList is not null)
        {
            List<string> titlesList = new List<string>();

            // Get the title of each slide in the slide order.
            foreach (var slideId in presentation.SlideIdList.Elements<SlideId>())
            {
                if (slideId.RelationshipId is null)
                {
                    continue;
                }

                SlidePart slidePart = (SlidePart)presentationPart.GetPartById(slideId.RelationshipId!);

                // Get the slide title.
                string title = GetSlideTitle(slidePart);

                // An empty title can also be added.
                titlesList.Add(title);
            }

            return titlesList;
        }

    }

    return null;
}

// Get the title string of the slide.
static string GetSlideTitle(SlidePart slidePart)
{
    if (slidePart is null)
    {
        throw new ArgumentNullException("presentationDocument");
    }

    // Declare a paragraph separator.
    string? paragraphSeparator = null;

    if (slidePart.Slide is not null)
    {
        // Find all the title shapes.
        var shapes = from shape in slidePart.Slide.Descendants<Shape>()
                     where IsTitleShape(shape)
                     select shape;

        StringBuilder paragraphText = new StringBuilder();

        foreach (var shape in shapes)
        {
            var paragraphs = shape.TextBody?.Descendants<D.Paragraph>();
            if (paragraphs is null)
            {
                continue;
            }

            // Get the text in each paragraph in this shape.
            foreach (var paragraph in paragraphs)
            {
                // Add a line break.
                paragraphText.Append(paragraphSeparator);

                foreach (var text in paragraph.Descendants<D.Text>())
                {
                    paragraphText.Append(text.Text);
                }

                paragraphSeparator = "\n";
            }
        }

        return paragraphText.ToString();
    }

    return string.Empty;
}

// Determines whether the shape is a title shape.
static bool IsTitleShape(Shape shape)
{
    PlaceholderShape? placeholderShape = shape.NonVisualShapeProperties?.ApplicationNonVisualDrawingProperties?.GetFirstChild<PlaceholderShape>();

    if (placeholderShape is not null && placeholderShape.Type is not null && placeholderShape.Type.HasValue)
    {
        return placeholderShape.Type == PlaceholderValues.Title || placeholderShape.Type == PlaceholderValues.CenteredTitle;
    }

    return false;
}

另请参阅

Open XML SDK 类库参考