如何:打开演示文稿文档以进行只读访问

上次修改时间: 2011年1月13日

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

本文内容
如何打开文件进行只读访问
创建 PresentationDocument 类的实例
基本演示文稿文档结构
示例代码的工作方式
示例代码

本主题介绍如何使用 Open XML SDK 2.0 for Microsoft Office 中的类以编程方式打开演示文稿文档以进行只读访问。

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

using System;
using System.Collections.Generic;
using DocumentFormat.OpenXml.Presentation;
using A = DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml;
using System.Text;
Imports System
Imports System.Collections.Generic
Imports DocumentFormat.OpenXml.Presentation
Imports A = DocumentFormat.OpenXml.Drawing
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml
Imports System.Text

如何打开文件进行只读访问

您可能希望打开演示文稿文档来阅读幻灯片。您可能要从幻灯片中提取信息、将幻灯片复制到幻灯片库或者列出幻灯片的标题。在此类情况下,您可能希望在执行这些操作的同时确保文档保持不变。为此,可以打开文档进行只读访问。本操作方法主题讨论以编程方式打开只读演示文稿文档的几种方法。

创建 PresentationDocument 类的实例

在 Open XML SDK 中,PresentationDocument 类表示演示文稿文档包。若要处理演示文稿文档,请首先创建 PresentationDocument 类的实例,然后处理该实例。若要基于文档创建该类的实例,请调用 Open 方法之一。提供了多个 Open 方法,每个方法具有不同的签名。下表包含 Open 方法的一部分重载,可以使用这些重载打开包。

名称

说明

Open(String, Boolean)

基于指定的文件创建 PresentationDocument 类的新实例。

Open(Stream, Boolean)

基于 I/O 流创建 PresentationDocument 类的新实例。

Open(Package)

基于指定的包创建 PresentationDocument 类的新实例。

前面的表包含两个接受布尔值作为第二个参数以指定文档是否可编辑的 Open 方法。若要打开文档以进行只读访问,请为此参数指定值 false。

例如,您可以按只读方式打开演示文稿文件,并将它分配给 PresentationDocument 对象,如下面的 using 语句所示。在此代码中,presentationFile 参数是一个字符串,表示要从中打开文档的文件路径。

using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
{
    // Insert other code here.
}
Using presentationDocument As PresentationDocument = PresentationDocument.Open(presentationFile, False)
    ' Insert other code here.
End Using

还可以使用上表中 Open 方法的第二个重载基于 I/O 流创建 PresentationDocument 类的实例。如果您的 Microsoft SharePoint Foundation 2010 应用程序使用流 I/O 并且您希望使用 Open XML SDK 2.0 处理文档,则可以使用此方法。以下代码段基于流打开文档。

Stream stream = File.Open(strDoc, FileMode.Open);
using (PresentationDocument presentationDocument =
    PresentationDocument.Open(stream, false)) 
{
    // Place other code here.
}
Dim stream As Stream = File.Open(strDoc, FileMode.Open)
Using presentationDocument As PresentationDocument = PresentationDocument.Open(stream, False)
    ' Other code goes here.
End Using

假定您的应用程序使用 .NET Framework 类库的 System.IO.Packaging 命名空间中的 Open XML 支持,并且您希望使用 Open XML SDK 2.0 以只读方式处理包。Open XML SDK 2.0 包含一个接受 Package 作为唯一参数的方法重载。没有布尔参数指明是否应该打开文档以进行编辑。建议的方法是先以只读方式打开包,然后再创建 PresentationDocument 类的实例。下面的代码段执行此操作。

Package presentationPackage = Package.Open(filepath, FileMode.Open, FileAccess.Read);
using (PresentationDocument presentationDocument =
    PresentationDocument.Open(presentationPackage))
{
    // Other code goes here.
}
Dim presentationPackage As Package = Package.Open(filepath, FileMode.Open, FileAccess.Read)
Using presentationDocument As PresentationDocument = PresentationDocument.Open(presentationPackage)
    ' Other code goes here.
End Using

基本演示文稿文档结构

PresentationML 文档的基本文档结构包含大量部件,在这些部件中,主部件是包含演示文稿定义的部件。来自 ISO/IEC 29500(该链接可能指向英文页面) 规范的以下文本介绍 PresentationML 包的整体形式。

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

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

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

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

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

© ISO/IEC29500: 2008。

以下 XML 代码段表示包含用 ID 267 和 256 表示的两个幻灯片的演示文稿。ID 属性指定在整个演示文稿中包含唯一值的幻灯片标识符。此属性的可能值介于 256 和 2147483647 之间。

<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>

示例代码的工作方式

在示例代码中,在 using 语句中打开演示文稿文档以进行只读访问后,将 PresentationPart 实例化,并打开幻灯片列表。然后获取第一个幻灯片的关系 ID。

// Get the relationship ID of the first slide.
PresentationPart part = ppt.PresentationPart;
OpenXmlElementList slideIds = part.Presentation.SlideIdList.ChildElements;
string relId = (slideIds[index] as SlideId).RelationshipId;
' Get the relationship ID of the first slide.
Dim part As PresentationPart = ppt.PresentationPart
Dim slideIds As OpenXmlElementList = part.Presentation.SlideIdList.ChildElements
Dim relId As String = (TryCast(slideIds(index), SlideId)).RelationshipId

您从关系 ID relId 获取幻灯片部件,然后通过使用 StringBuilder 构建文本字符串来获取幻灯片的内部文本。

// Get the slide part from the relationship ID.
SlidePart slide = (SlidePart)part.GetPartById(relId);

// Build a StringBuilder object.
StringBuilder paragraphText = new StringBuilder();

// Get the inner text of the slide.
IEnumerable<A.Text> texts = slide.Slide.Descendants<A.Text>();
foreach (A.Text text in texts)
{
    paragraphText.Append(text.Text);
}
sldText = paragraphText.ToString();
' Get the slide part from the relationship ID.
Dim slide As SlidePart = CType(part.GetPartById(relId), SlidePart)

' Build a StringBuilder object.
Dim paragraphText As New StringBuilder()

' Get the inner text of the slide.
Dim texts As IEnumerable(Of A.Text) = slide.Slide.Descendants(Of A.Text)()
For Each text As A.Text In texts
    paragraphText.Append(text.Text)
Next text
sldText = paragraphText.ToString()

幻灯片的内部文本(即 GetSlideIdAndText 方法的 out 参数)将传递回要显示的 main 方法。

重要说明重要说明

此示例仅显示演示文稿文件中的文本。不显示非文本部件,如形状或图形。

示例代码

下面的示例打开演示文稿文件以进行只读访问并获取指定索引处的幻灯片的内部文本。若要调用 GetSlideIdAndText 方法,请传入演示文稿文档的完整路径。另请传入 out 参数 sldText(将在方法本身中为它分配值),然后可以在主程序中显示它的值。例如,对 GetSlideIdAndText 方法的以下调用获取名为"Myppt13.pptx"的演示文稿文件中第二个幻灯片的内部文本。

提示

此程序中最可能出现的异常是 ArgumentOutOfRangeException 异常。例如,如果您的文件具有两个幻灯片,但是您希望显示编号为 4 的幻灯片中的文本,则可能会引发该异常。因此,调用 GetSlideIdAndText 方法时最好使用 try 块,如下面的示例所示。

string file = @"C:\Users\Public\Documents\Myppt13.pptx";
string slideText;
int index = 1;
try
{
    GetSlideIdAndText(out slideText, file, index);
    Console.WriteLine("The text in the slide #{0} is: {1}", index + 1, slideText);
}
catch (ArgumentOutOfRangeException exp)
{
    Console.WriteLine(exp.Message);
}
Dim file As String = "C:\Users\Public\Documents\Myppt13.pptx"
Dim slideText As String = Nothing
Dim index As Integer = 1
Try
    GetSlideIdAndText(slideText, file, index)
    Console.WriteLine("The text in the slide #{0} is: {1}", index + 1, slideText)
Catch exp As ArgumentOutOfRangeException
    Console.WriteLine(exp.Message)
End Try

以下是用 C# 和 Visual Basic 编写的完整代码列表。

public static void GetSlideIdAndText(out string sldText, string docName, int index)
{
    using (PresentationDocument ppt = PresentationDocument.Open(docName, false))
    {
        // Get the relationship ID of the first slide.
        PresentationPart part = ppt.PresentationPart;
        OpenXmlElementList slideIds = part.Presentation.SlideIdList.ChildElements;
        string relId = (slideIds[index] as SlideId).RelationshipId;
        relId = (slideIds[index] as SlideId).RelationshipId;

        // Get the slide part from the relationship ID.
        SlidePart slide = (SlidePart)part.GetPartById(relId);

        // Build a StringBuilder object.
        StringBuilder paragraphText = new StringBuilder();

        // Get the inner text of the slide:
        IEnumerable<A.Text> texts = slide.Slide.Descendants<A.Text>();
        foreach (A.Text text in texts)
        {
            paragraphText.Append(text.Text);
        }
        sldText = paragraphText.ToString();
    }
}
Public Sub GetSlideIdAndText(ByRef sldText As String, ByVal docName As String, ByVal index As Integer)
    Using ppt As PresentationDocument = PresentationDocument.Open(docName, False)
        ' Get the relationship ID of the first slide.
        Dim part As PresentationPart = ppt.PresentationPart
        Dim slideIds As OpenXmlElementList = part.Presentation.SlideIdList.ChildElements
        Dim relId As String = TryCast(slideIds(index), SlideId).RelationshipId
        relId = TryCast(slideIds(index), SlideId).RelationshipId

        ' Get the slide part from the relationship ID.
        Dim slide As SlidePart = DirectCast(part.GetPartById(relId), SlidePart)

        ' Build a StringBuilder object.
        Dim paragraphText As New StringBuilder()

        ' Get the inner text of the slide:
        Dim texts As IEnumerable(Of A.Text) = slide.Slide.Descendants(Of A.Text)()
        For Each text As A.Text In texts
            paragraphText.Append(text.Text)
        Next
        sldText = paragraphText.ToString()
    End Using
End Sub

请参阅

引用

Class Library Reference