打开字处理文档以便进行只读访问

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


何时打开文档以进行只读访问

有时,您需要打开文档以检查或检索某些信息,并且希望以一种可确保文档保持未更改的方式执行此操作。 在此类情况下,您希望打开文档以进行只读访问。 本操作方法主题讨论了若干种以编程方式打开只读字处理文档的方法。


创建 WordprocessingDocument 对象

在 Open XML SDK 中,WordprocessingDocument 类表示 Word 文档包。 若要使用 Word 文档,请首先从文档中创建 WordprocessingDocument 类的一个实例,然后使用该实例。 从文档中创建实例后,您即可获得对包含文档文本的主文档部件的访问权限。 每个 Open XML 包都会包含一些数量的部件。 WordProcessingDocument 至少必须包含一个用作文档主文本的容器的主文档部件。 包中还可以包含其他部件。 请注意,在 Word 文档中,主文档部件中的文本在此包中使用 WordprocessingML 标记表示为 XML 形式。

若要从文档中创建类实例,请调用 Open 方法之一。 提供了多个 Open 方法,每个方法具有不同的签名。 下表中列出了允许您指定文档是否可编辑的方法。

Open 方法 类库参考主题 说明
Open(String, Boolean) Open(String, Boolean) 从指定文件创建 WordprocessingDocument 类的实例。
Open(Stream, Boolean) Open(Stream, Boolean) 从指定 IO 流创建 WordprocessingDocument 类的实例。
Open(String, Boolean, OpenSettings) Open(String, Boolean, OpenSettings) 从指定文件创建 WordprocessingDocument 类的实例。
Open(Stream, Boolean, OpenSettings) Open(Stream, Boolean, OpenSettings) 从指定 I/O 流创建 WordprocessingDocument 类的实例。

上表只列出了那些接受布尔值作为第二个参数以指定文档是否可编辑的 Open 方法。 若要打开文档以进行只读访问,请为此参数指定 false。

请注意,其中两个 Open 方法会基于作为第一个参数的字符串创建 WordprocessingDocument 类的实例。 代码示例中的第一个示例使用此技术。 它使用上表中的第一个 Open 方法;此方法的签名需要两个参数。 第一个参数采用表示要从中打开文档的完整路径文件名的字符串。 第二个参数是 truefalse;此示例使用 false 并指示您是否需要打开该文件以进行编辑。

以下代码示例调用 Open 方法。

    // Open a WordprocessingDocument for read-only access based on a filepath.
    using (WordprocessingDocument wordDocument =
        WordprocessingDocument.Open(filepath, false))

其他两个 Open 方法基于输入/输出流创建 WordprocessingDocument 类的实例。 例如,如果你有一个使用流输入/输出的Microsoft SharePoint Foundation 2010应用程序,并且想要使用 Open XML SDK 来处理文档,则可以使用此方法。

以下代码示例基于流打开文档。

    Stream stream = File.Open(strDoc, FileMode.Open);
    // Open a WordprocessingDocument for read-only access based on a stream.
    using (WordprocessingDocument wordDocument =
        WordprocessingDocument.Open(stream, false))

假设你有一个应用程序在 .NET Framework 类库的 System.IO.Packaging 命名空间中采用 Open XML 支持,并且你希望使用 Open XML SDK 来处理只读包。 虽然 Open XML SDK 包含接受 Package 作为第一个参数的方法重载,但没有一个重载将布尔值作为第二个参数来指示是否应打开文档进行编辑。

建议的方法是首先以只读方式打开包,然后再创建 WordprocessingDocument 类的实例,如代码示例中的第二个示例所示。 下面的代码示例执行此操作。

    // Open System.IO.Packaging.Package.
    Package wordPackage = Package.Open(filepath, FileMode.Open, FileAccess.Read);

    // Open a WordprocessingDocument based on a package.
    using (WordprocessingDocument wordDocument =
        WordprocessingDocument.Open(wordPackage))

打开 Word 文档包后,您即可访问主文档部件。 若要访问主文档部件的正文,请分配一个对现有文档正文的引用,如以下代码示例所示。

    // Assign a reference to the existing document body.
    Body body = wordprocessingDocument.MainDocumentPart.Document.Body;

WordProcessingML 文档的结构

WordProcessingML 文档的基本文档结构由 documentbody 元素组成,后跟一个或多个块级元素,如表示段落的 p。 一个段落包含一个或多个 r 元素。 r 代表一段连续文本,它是具有一组共同属性(如格式设置)的文本区域。 一段连续文本包含一个或多个 t 元素。 t 元素包含一个文本区域。 以下代码示例显示包含文本"Example text."的文档的 WordprocessingML 标记。

    <w:document xmlns:w="https://schemas.openxmlformats.org/wordprocessingml/2006/main">
      <w:body>
        <w:p>
          <w:r>
            <w:t>Example text.</w:t>
          </w:r>
        </w:p>
      </w:body>
    </w:document>

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

WordprocessingML 元素 Open XML SDK 类 说明
document Document 主文档部件的根元素
body Body 块级结构(如段落、表格、批注和 ISO/IEC 29500 规范中指定的其他项)的容器。
p Paragraph 段落。
r Run 一段连续文本。
t Text 文本范围。

有关 WordprocessingML 文档的各个部分和元素的整体结构的详细信息,请参阅 WordprocessingML 文档的结构


生成 WordprocessingML 标记以添加文本并尝试保存

该代码示例演示您应如何添加某些文本并尝试保存更改以表明访问是只读的。 在您有权访问主文档部件的正文后,请通过添加 ParagraphRunText 类的实例来添加文本。 这将生成必需的 WordprocessingML 标记。 以下代码示例添加段落和一段连续文本。

    // Attempt to add some text.
    Paragraph para = body.AppendChild(new Paragraph());
    Run run = para.AppendChild(new Run());
    run.AppendChild(new Text("Append text in body, but text is not saved - OpenWordprocessingDocumentReadonly"));

    // Call Save to generate an exception and show that access is read-only.
    wordDocument.MainDocumentPart.Document.Save();

示例代码

此处显示的第一个示例方法 OpenWordprocessingDocumentReadOnly 打开一个 Word 文档进行只读访问。 可通过传递要打开的文件的完整路径来调用此方法。 例如,以下代码示例打开 Public Documents 文件夹中的 Word12.docx 文件以进行只读访问。

    OpenWordprocessingDocumentReadonly(@"c:\Users\Public\Public Documents\Word12.docx");

第二个示例方法 OpenWordprocessingPackageReadonly 显示如何从 System.IO.Packaging.Package 打开 Word 文档进行只读访问。 可通过传递要打开的文件的完整路径来调用此方法。 例如,以下代码打开 Public Documents 文件夹中的 Word12.docx 文件以进行只读访问。

    OpenWordprocessingPackageReadonly(@"c:\Users\Public\Public Documents\Word12.docx");

重要

[!重要信息] 由于打开文件是为进行只读访问,所以如果取消对用于保存文件的语句的注释,程序将引发 IOException

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


using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;

OpenWordprocessingDocumentReadonly(args[0]);

static void OpenWordprocessingDocumentReadonly(string filepath)
{
    // Open a WordprocessingDocument based on a filepath.
    using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(filepath, false))
    {
        if (wordDocument is null)
        {
            throw new ArgumentNullException(nameof(wordDocument));
        }
        // Assign a reference to the existing document body.
        MainDocumentPart mainDocumentPart = wordDocument.MainDocumentPart ?? wordDocument.AddMainDocumentPart();
        mainDocumentPart.Document ??= new Document();

        Body body = mainDocumentPart.Document.Body ?? mainDocumentPart.Document.AppendChild(new Body());

        // Attempt to add some text.
        Paragraph para = body.AppendChild(new Paragraph());
        Run run = para.AppendChild(new Run());
        run.AppendChild(new Text("Append text in body, but text is not saved - OpenWordprocessingDocumentReadonly"));

        // Call Save to generate an exception and show that access is read-only.
        //mainDocumentPart.Document.Save();
    }
}

另请参阅