替换字处理文档中的主题部分

本主题演示如何使用 Open XML SDK for Office 中的类以编程方式替换字处理文档中的文档部件。

包和文档部件

Open XML 文档存储为包,其格式由 ISO/IEC 29500 定义。 包可以具有多个彼此之间存在关系的部件。 部件之间的关系控制文档的类别。 如果文档的包关系项包含与主文档部件的关系,可将文档定义为字处理文档。 如果文档的包关系项包含与演示文稿部件的关系,可将文档定义为演示文稿文档。 如果文档的包关系项包含与工作簿部件的关系,可将文档定义为电子表格文档。 在本操作方法主题中,您将使用字处理文档包。

获取 WordprocessingDocument 对象

在示例代码中,首先通过实例化 类来打开字处理文件, WordprocessingDocument 如以下 using 语句所示。 在同一语句中,使用 Open 方法打开字处理文件文档,并将布尔参数设置为 true 以启用编辑文档。

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))

在 v3.0.0+ 中, Close() 已删除 方法,转而依赖于 using 语句。 它确保在 Dispose() 到达右大括号时自动调用 方法。 using 语句后面的块为 using 语句中创建或指定的对象设定范围。 WordprocessingDocument由于 Open XML SDK 中的 类会自动保存并关闭对象作为其IDisposable实现的一using部分,并且由于Dispose()在退出块时会自动调用,因此无需显式调用 Save()Dispose() ,只要使用 语句。

如何在 Word 包中更改主题

如果要更改Word文档中的主题,请单击功能区“设计”,然后单击“主题”。 "主题"下拉菜单将打开。 若要选择其中一个内置主题并将其应用于Word文档,请单击主题图标。 也可以使用“浏览主题...”选项,在计算机中查找并应用主题文件。

主题元素的结构

主题元素由颜色、字体和格式方案组成。 在本操作方法主题中,您将学习如何以编程方式更改主题。 因此,熟悉主题元素会很有帮助。 ISO/IEC 29500(该链接可能指向英文页面) 规范中的以下信息在处理此元素时会很有用。

此元素定义与共享样式表(或主题)关联的根级别复杂类型。 此元素保留通过主题提供给文档的所有不同的格式选项并定义在文档中使用主题对象时文档的总体外观。

[示例:请考虑以下图像示例中应用于演示文稿的不同主题。 在此示例中,可以查看主题如何影响演示文稿中不同对象的字体、颜色、背景、填充和效果。 示例结束]

主题示例

在此示例中,我们查看主题如何影响演示文稿中不同对象的字体、颜色、背景、填充和效果。 示例结束]

© ISO/IEC 29500:2016

下表列出 Theme 类可能的子类型。

PresentationML 元素 Open XML SDK 类 说明
<custClrLst/> CustomColorList 自定义颜色列表
<extLst/> ExtensionList 扩展名列表
<extraClrSchemeLst/> ExtraColorSchemeList 额外配色方案列表
<objectDefaults/> ObjectDefaults 对象默认值
<themeElements/> ThemeElements 主题元素

下面的 XML 架构段定义主题元素的四个部件。 元素themeElements是保存主题中定义的main格式的片段。 其他部分对 中包含的 themeElements信息提供替代、默认值和添加。 定义主题 CT_OfficeStyleSheet的复杂类型按以下方式定义:

    <complexType name="CT_OfficeStyleSheet">
       <sequence>
           <element name="themeElements" type="CT_BaseStyles" minOccurs="1" maxOccurs="1"/>
           <element name="objectDefaults" type="CT_ObjectStyleDefaults" minOccurs="0" maxOccurs="1"/>
           <element name="extraClrSchemeLst" type="CT_ColorSchemeList" minOccurs="0" maxOccurs="1"/>
           <element name="custClrLst" type="CT_CustomColorList" minOccurs="0" maxOccurs="1"/>
           <element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
       </sequence>
       <attribute name="name" type="xsd:string" use="optional" default=""/>
    </complexType>

此复杂类型还包含一个 CT_OfficeArtExtensionList,该类型用于此复杂类型的未来扩展性。

示例代码的工作方式

打开文件后,可以在 对象中wordDoc实例化 MainDocumentPart ,并删除旧主题部分。

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
{
    if (wordDoc?.MainDocumentPart?.ThemePart is null)
    {
        throw new ArgumentNullException("MainDocumentPart and/or Body and/or ThemePart is null.");
    }

    MainDocumentPart mainPart = wordDoc.MainDocumentPart;

    // Delete the old document part.
    mainPart.DeletePart(mainPart.ThemePart);

然后,可以创建添加新 ThemePart 对象并将其添加到 对象 MainDocumentPart 。 然后,通过使用 StreamReaderStreamWriter 对象添加内容,将主题从 themeFile 复制到 对象 ThemePart

// Add a new document part and then add content.
ThemePart themePart = mainPart.AddNewPart<ThemePart>();

using (StreamReader streamReader = new StreamReader(themeFile))
using (StreamWriter streamWriter = new StreamWriter(themePart.GetStream(FileMode.Create)))
{
    streamWriter.Write(streamReader.ReadToEnd());
}

示例代码

下面的代码示例演示如何将一个字处理文档中的主题文档部件替换为另一个包中的主题部件。 作为第二个参数传递的主题文件必须是采用 XML 格式的有效主题部件(如 Theme1.xml)。 您可以从已重命名为 .Zip 文件的现有文档或主题文件 (.THMX) 中提取此部件。 若要调用 方法 ReplaceTheme ,可以使用以下调用示例将主题从 和 arg[1] 复制到位于 arg[0]

string document = args[0];
string themeFile = args[1];

ReplaceTheme(document, themeFile);

运行程序后,打开Word文件,并注意到新主题更改。

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

// This method can be used to replace the theme part in a package.
static void ReplaceTheme(string document, string themeFile)
{
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
    {
        if (wordDoc?.MainDocumentPart?.ThemePart is null)
        {
            throw new ArgumentNullException("MainDocumentPart and/or Body and/or ThemePart is null.");
        }

        MainDocumentPart mainPart = wordDoc.MainDocumentPart;

        // Delete the old document part.
        mainPart.DeletePart(mainPart.ThemePart);
        // Add a new document part and then add content.
        ThemePart themePart = mainPart.AddNewPart<ThemePart>();

        using (StreamReader streamReader = new StreamReader(themeFile))
        using (StreamWriter streamWriter = new StreamWriter(themePart.GetStream(FileMode.Create)))
        {
            streamWriter.Write(streamReader.ReadToEnd());
        }
    }
}

另请参阅