创建段落样式并将其添加到字处理文档

本主题演示如何使用 Open XML SDK for Office 中的类以编程方式创建段落样式并将其添加到字处理文档。 本文包含一个演示此任务的示例 CreateAndAddParagraphStyle 方法,以及一个在必要时添加 styles 部分的补充示例方法。


CreateAndAddParagraphStyle 方法

CreateAndAddParagraphStyle 示例方法可用于向字处理文档添加样式。 您必须先获取对要将样式添加到的文档中的样式定义部分的引用。 有关如何执行此操作的详细信息和示例,请参阅调用示例方法部分。

该方法接受四个参数,分别指示:对样式定义部分的引用、样式的样式 ID(内部标识符)、样式的名称(在用户界面中供外部使用)以及任何样式别名(在用户界面中使用的其他名称)(可选)。

    public static void CreateAndAddParagraphStyle(StyleDefinitionsPart styleDefinitionsPart,
        string styleid, string stylename, string aliases="")

该方法的完整代码列表位于示例代码部分。


关于样式 ID、样式名称和别名

样式 ID 由文档用于引用样式,可被视为其主要标识符。 通常情况下,您可以使用样式 ID 来标识代码中的样式。 样式还可在用户界面中具有单独的显示名称。 因此,样式名称通常以正确的大小写和空格显示(例如 Heading 1),而样式 ID 则比较简洁(例如 heading1),旨在供内部使用。 别名指定可由应用程序的用户界面使用的其他样式名称。

例如,考虑从样式定义提取的以下 XML 代码示例。

    <w:style w:type="paragraph" w:styleId="OverdueAmountPara" . . .
      <w:aliases w:val="Late Due, Late Amount" />
      <w:name w:val="Overdue Amount Para" />
    . . .
    </w:style>

样式元素的 styleId 属性保存样式的主要内部标识符,即样式 ID (OverdueAmountPara)。 别名元素指定两个其他样式名称(Late Due 和 Late Amount),以逗号分隔。 每个名称必须由一个或多个逗号分隔。 最后,名称元素指定主要样式名称,即通常显示在应用程序的用户界面中的名称。


调用示例方法

通过 CreateAndAddParagraphStyle 示例方法可使用 Open XML SDK 创建已命名样式,并将其添加到字处理文档。 以下代码示例演示如何打开和获取对字处理文档的引用,检索对文档的样式定义部分的引用,然后调用 CreateAndAddParagraphStyle 方法。

若要调用该方法,请传递对样式定义部分的引用作为第一个参数,样式的样式 ID 作为第二个参数,样式的名称作为第三个参数,以及任何样式别名作为第四个参数(可选)。 例如,以下代码将在名为 CreateAndAddParagraphStyle.docx 的示例文件中创建"Overdue Amount Para"段落样式。 它还会添加一段文本,并将该样式应用于该段落。

    string strDoc = @"C:\Users\Public\Documents\CreateAndAddParagraphStyle.docx";

    using (WordprocessingDocument doc = 
        WordprocessingDocument.Open(strDoc, true))
    {
        // Get the Styles part for this document.
        StyleDefinitionsPart part =
            doc.MainDocumentPart.StyleDefinitionsPart;

        // If the Styles part does not exist, add it and then add the style.
        if (part == null)
        {
            part = AddStylesPartToPackage(doc);
        }

        // Set up a variable to hold the style ID.
        string parastyleid = "OverdueAmountPara";

        // Create and add a paragraph style to the specified styles part 
        // with the specified style ID, style name and aliases.
        CreateAndAddParagraphStyle(part,
            parastyleid,
            "Overdue Amount Para",
            "Late Due, Late Amount");
        
        // Add a paragraph with a run and some text.
        Paragraph p = 
            new Paragraph(
                new Run(
                    new Text("This is some text in a run in a paragraph.")));
        
        // Add the paragraph as a child element of the w:body element.
        doc.MainDocumentPart.Document.Body.AppendChild(p);

        // If the paragraph has no ParagraphProperties object, create one.
        if (p.Elements<ParagraphProperties>().Count() == 0)
        {
            p.PrependChild<ParagraphProperties>(new ParagraphProperties());
        }

        // Get a reference to the ParagraphProperties object.
        ParagraphProperties pPr = p.ParagraphProperties;
        
        // If a ParagraphStyleId object doesn't exist, create one.
        if (pPr.ParagraphStyleId == null)
            pPr.ParagraphStyleId = new ParagraphStyleId();

        // Set the style of the paragraph.
        pPr.ParagraphStyleId.Val = parastyleid;
    }

样式类型

WordprocessingML 支持六种样式类型,其中四种可使用样式元素中的类型属性指定。 来自 ISO/IEC 29500 规范第 17.7.4.17 节的以下信息介绍了样式类型。

样式类型 指的是样式上的属性,用于定义使用此样式定义创建的样式的类型。 根据样式定义的类型属性的值,WordprocessingML 支持六种样式定义类型:

  • 段落样式

  • 字符样式

  • 链接样式(段落 + 字符)[注释:通过链接元素实现 (§17.7.4.6)。 注释结束]

  • 表样式

  • 编号样式

  • 默认段落 + 字符属性

示例:考虑文档中名为“标题 1”的样式,如下所示:

    <w:style w:type="paragraph" w:styleId="Heading1">
      <w:name w:val="heading 1"/>
      <w:basedOn w:val="Normal"/>
      <w:next w:val="Normal"/>
      <w:link w:val="Heading1Char"/>
      <w:uiPriority w:val="1"/>
      <w:qformat/>
      <w:rsid w:val="00F303CE"/>
      …
    </w:style>

该类型属性的值为 paragraph,指示以下样式定义为段落样式。

© ISO/IEC29500: 2008.

您可通过在样式元素的类型属性中指定相应的值来设置段落、字符、表和编号样式。


段落样式类型

您可通过将样式元素上的类型属性设置为"paragraph"来将段落指定为样式类型。

ISO/IEC 29500 规范的第 17.7.8 节中的以下信息讨论段落样式。 请注意,§ 后的章节编号指示 ISO 规范中的章节。

17.7.8 段落样式

段落样式 是应用于整个段落的内容以及段落标记的样式。 此定义暗示该样式可定义字符属性(应用于文档中的文本的属性)和段落属性(应用于段落的位置和外观的属性)。 段落样式无法由文档中的连续文本引用;它们应由段落的段落属性元素中的 pStyle 元素 (§17.3.1.27) 引用。

段落样式具有三个特定于定义样式类型的特征:

  • 样式上的类型属性的值为 paragraph,指示以下样式定义为段落样式。

  • next 元素定义一种编辑行为,当在此样式的段落末尾按 Enter 时,该行为提供将自动应用于下一段落的段落样式。

  • 样式分别使用 pPrrPr 元素指定段落级别和字符级别的属性。 在这种情况下,连续文本属性是应用于段落中的每段连续文本的属性集。

然后,会通过在段落属性 (Property) 的 pStyle 元素中引用此样式的 styleId 属性 (Attribute) 值来将段落样式应用于各个段落。

© ISO/IEC29500: 2008.


代码的工作方式

CreateAndAddParagraphStyle 方法先在样式部分中检索对样式元素的引用。 样式元素是该部分的根元素,包含所有单个样式元素。 如果引用为空,则会创建样式元素并将其保存到该部分。

    // Access the root element of the styles part.
        Styles styles = styleDefinitionsPart.Styles;
        if (styles == null)
        {
            styleDefinitionsPart.Styles = new Styles();
            styleDefinitionsPart.Styles.Save();
        }

创建样式

为了创建样式,代码会实例化 Style 类并设置某些属性,例如样式类型 (段落) StyleId、样式是否为 CustomStyle 以及样式是否为其类型的默认样式。

    // Create a new paragraph style element and specify some of the attributes.
    Style style = new Style() { Type = StyleValues.Paragraph,
        StyleId = styleid,
        CustomStyle = true,
        Default = false
    };

该代码生成以下 XML。

    <w:styles xmlns:w="https://schemas.openxmlformats.org/wordprocessingml/2006/main">
      <w:style w:type="paragraph" w:styleId="OverdueAmountPara" w:default="false" w:customStyle="true">
      </w:style>
    </w:styles>

接下来,该代码创建样式的子元素,这些元素用于定义样式的属性。 若要创建元素,请实例化其相应的类,然后调用 Append ([]) 方法将子元素添加到样式中。 有关这些属性的详细信息,请参阅 ISO/IEC 29500 规范的第 17.7 部分。

    // Create and add the child elements (properties of the style).
    Aliases aliases1 = new Aliases() { Val = aliases };
    AutoRedefine autoredefine1 = new AutoRedefine() { Val = OnOffOnlyValues.Off };
    BasedOn basedon1 = new BasedOn() { Val = "Normal" };
    LinkedStyle linkedStyle1 = new LinkedStyle() { Val = "OverdueAmountChar" };
    Locked locked1 = new Locked() { Val = OnOffOnlyValues.Off };
    PrimaryStyle primarystyle1 = new PrimaryStyle() { Val = OnOffOnlyValues.On };
    StyleHidden stylehidden1 = new StyleHidden() { Val = OnOffOnlyValues.Off };
    SemiHidden semihidden1 = new SemiHidden() { Val = OnOffOnlyValues.Off };
    StyleName styleName1 = new StyleName() { Val = stylename };
    NextParagraphStyle nextParagraphStyle1 = new NextParagraphStyle() { Val = "Normal" };
    UIPriority uipriority1 = new UIPriority() { Val = 1 };
    UnhideWhenUsed unhidewhenused1 = new UnhideWhenUsed() { Val = OnOffOnlyValues.On };
    if (aliases != "")
        style.Append(aliases1);
    style.Append(autoredefine1);
    style.Append(basedon1);
    style.Append(linkedStyle1);
    style.Append(locked1);
    style.Append(primarystyle1);
    style.Append(stylehidden1);
    style.Append(semihidden1);
    style.Append(styleName1);
    style.Append(nextParagraphStyle1);
    style.Append(uipriority1);
    style.Append(unhidewhenused1);

接下来,代码实例化 StyleRunProperties 对象,以创建 rPr (run Properties) 元素。 您可在此元素中指定应用于样式的字符属性(如字体和颜色)。 然后,这些属性会追加为 rPr 元素的子级。

创建连续文本属性后,该代码会将 rPr 元素追加到样式,并将样式元素追加到样式部分中的样式根元素。

    // Create the StyleRunProperties object and specify some of the run properties.
    StyleRunProperties styleRunProperties1 = new StyleRunProperties();
    Bold bold1 = new Bold();
    Color color1 = new Color() { ThemeColor = ThemeColorValues.Accent2 };
    RunFonts font1 = new RunFonts() { Ascii = "Lucida Console" };
    Italic italic1 = new Italic();
    // Specify a 12 point size.
    FontSize fontSize1 = new FontSize() { Val = "24" };
    styleRunProperties1.Append(bold1);
    styleRunProperties1.Append(color1);
    styleRunProperties1.Append(font1);
    styleRunProperties1.Append(fontSize1);
    styleRunProperties1.Append(italic1);

    // Add the run properties to the style.
    style.Append(styleRunProperties1);

    // Add the style to the styles part.
    styles.Append(style);

应用段落样式

创建样式后,可通过在段落属性 (Property) 的 pStyle 元素中引用此样式的 styleId 属性 (Attribute) 值来将其应用到段落。 以下示例代码演示如何将样式应用于变量 p 引用的段落。 要应用的样式的样式 ID 存储在 parastyleid 变量中,并且 ParagraphStyleId 属性表示段落属性的 pStyle 元素。

    // If the paragraph has no ParagraphProperties object, create one.
    if (p.Elements<ParagraphProperties>().Count() == 0)
    {
        p.PrependChild<ParagraphProperties>(new ParagraphProperties());
    }

    // Get a reference to the ParagraphProperties object.
    ParagraphProperties pPr = p.ParagraphProperties;

    // If a ParagraphStyleId object does not exist, create one.
    if (pPr.ParagraphStyleId == null)
        pPr.ParagraphStyleId = new ParagraphStyleId();

    // Set the style of the paragraph.
    pPr.ParagraphStyleId.Val = parastyleid;

示例代码

下面是 C# 和 Visual Basic 中的完整 CreateAndAddParagraphStyle 示例代码。

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

CreateAndAddParagraphStyle(args[0], args[1], args[2], args[3]);

// Create a new paragraph style with the specified style ID, primary style name, and aliases and 
// add it to the specified style definitions part.
static void CreateAndAddParagraphStyle(string filePath, string styleid, string stylename, string aliases = "")
{
    using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(filePath, true))
    {
        // Access the root element of the styles part.
        Styles? styles = wordprocessingDocument?.MainDocumentPart?.StyleDefinitionsPart?.Styles ?? AddStylesPartToPackage(wordprocessingDocument).Styles;

        if (styles is not null)
        {

            // Create a new paragraph style element and specify some of the attributes.
            Style style = new Style()
            {
                Type = StyleValues.Paragraph,
                StyleId = styleid,
                CustomStyle = true,
                Default = false
            };

            // Create and add the child elements (properties of the style).
            Aliases aliases1 = new Aliases() { Val = aliases };
            AutoRedefine autoredefine1 = new AutoRedefine() { Val = OnOffOnlyValues.Off };
            BasedOn basedon1 = new BasedOn() { Val = "Normal" };
            LinkedStyle linkedStyle1 = new LinkedStyle() { Val = "OverdueAmountChar" };
            Locked locked1 = new Locked() { Val = OnOffOnlyValues.Off };
            PrimaryStyle primarystyle1 = new PrimaryStyle() { Val = OnOffOnlyValues.On };
            StyleHidden stylehidden1 = new StyleHidden() { Val = OnOffOnlyValues.Off };
            SemiHidden semihidden1 = new SemiHidden() { Val = OnOffOnlyValues.Off };
            StyleName styleName1 = new StyleName() { Val = stylename };
            NextParagraphStyle nextParagraphStyle1 = new NextParagraphStyle() { Val = "Normal" };
            UIPriority uipriority1 = new UIPriority() { Val = 1 };
            UnhideWhenUsed unhidewhenused1 = new UnhideWhenUsed() { Val = OnOffOnlyValues.On };
            if (aliases != "")
                style.Append(aliases1);
            style.Append(autoredefine1);
            style.Append(basedon1);
            style.Append(linkedStyle1);
            style.Append(locked1);
            style.Append(primarystyle1);
            style.Append(stylehidden1);
            style.Append(semihidden1);
            style.Append(styleName1);
            style.Append(nextParagraphStyle1);
            style.Append(uipriority1);
            style.Append(unhidewhenused1);

            // Create the StyleRunProperties object and specify some of the run properties.
            StyleRunProperties styleRunProperties1 = new StyleRunProperties();
            Bold bold1 = new Bold();
            Color color1 = new Color() { ThemeColor = ThemeColorValues.Accent2 };
            RunFonts font1 = new RunFonts() { Ascii = "Lucida Console" };
            Italic italic1 = new Italic();
            // Specify a 12 point size.
            FontSize fontSize1 = new FontSize() { Val = "24" };
            styleRunProperties1.Append(bold1);
            styleRunProperties1.Append(color1);
            styleRunProperties1.Append(font1);
            styleRunProperties1.Append(fontSize1);
            styleRunProperties1.Append(italic1);

            // Add the run properties to the style.
            style.Append(styleRunProperties1);

            // Add the style to the styles part.
            styles.Append(style);
        }
    }
}

// Add a StylesDefinitionsPart to the document.  Returns a reference to it.
static StyleDefinitionsPart AddStylesPartToPackage(WordprocessingDocument? doc)
{
    StyleDefinitionsPart part;

    if (doc?.MainDocumentPart is null)
    {
        throw new ArgumentNullException("MainDocumentPart is null.");
    }

    part = doc.MainDocumentPart.AddNewPart<StyleDefinitionsPart>();
    Styles root = new Styles();
    root.Save(part);
    return part;
}

另请参阅