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

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


CreateAndAddParagraphStyle 方法

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

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

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 作为第二个参数,样式的名称作为第三个参数,以及任何样式别名作为第四个参数(可选)。 例如,以下代码创建“逾期金额 Para”段落样式。 它还会添加一段文本,并将该样式应用于该段落。

string strDoc = args[0];

using (WordprocessingDocument doc = WordprocessingDocument.Open(strDoc, true))
{
    if (doc is null)
    {
        throw new ArgumentNullException("document could not be opened");
    }

    MainDocumentPart mainDocumentPart = doc.MainDocumentPart ?? doc.AddMainDocumentPart();

    // Get the Styles part for this document.
    StyleDefinitionsPart? part = mainDocumentPart.StyleDefinitionsPart;

    // If the Styles part does not exist, add it and then add the style.
    if (part is 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.
    mainDocumentPart.Document ??= new Document();
    mainDocumentPart.Document.Body ??= new Body();

    mainDocumentPart.Document.Body.AppendChild(p);

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

    // Get a reference to the ParagraphProperties object.
    p.ParagraphProperties ??= new ParagraphProperties();
    ParagraphProperties pPr = p.ParagraphProperties;

    // If a ParagraphStyleId object doesn't exist, create one.
    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/IEC 29500:2016

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


段落样式类型

您可通过将样式元素上的类型属性设置为"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/IEC 29500:2016


代码的工作方式

方法 CreateAndAddParagraphStyle 首先检索对 styles 部件中 styles 元素的引用。 样式元素是该部分的根元素,包含所有单个样式元素。 如果引用为 null,则创建 styles 元素。

// Access the root element of the styles part.
Styles? styles = styleDefinitionsPart.Styles;

if (styles is null)
{
    styleDefinitionsPart.Styles = new Styles();
    styles = styleDefinitionsPart.Styles;
}

创建样式

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

// 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="http://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 (string.IsNullOrWhiteSpace(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 (运行属性) 元素。 您可在此元素中指定应用于样式的字符属性(如字体和颜色)。 然后,这些属性将追加为 元素的子级 rPr

创建运行属性时,代码会将 rPr 元素追加到样式,并将 style 元素追加到 styles 部件中的 styles 根元素。

// 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(new ParagraphProperties());
}

// Get a reference to the ParagraphProperties object.
p.ParagraphProperties ??= new ParagraphProperties();
ParagraphProperties pPr = p.ParagraphProperties;

// If a ParagraphStyleId object doesn't exist, create one.
pPr.ParagraphStyleId ??= new ParagraphStyleId();

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

示例代码

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

// 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(StyleDefinitionsPart styleDefinitionsPart, string styleid, string stylename, string aliases = "")
{
    // Access the root element of the styles part.
    Styles? styles = styleDefinitionsPart.Styles;

    if (styles is null)
    {
        styleDefinitionsPart.Styles = new Styles();
        styles = styleDefinitionsPart.Styles;
    }

    // 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 (string.IsNullOrWhiteSpace(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>();
    part.Styles = new Styles();

    return part;
}

string strDoc = args[0];

using (WordprocessingDocument doc = WordprocessingDocument.Open(strDoc, true))
{
    if (doc is null)
    {
        throw new ArgumentNullException("document could not be opened");
    }

    MainDocumentPart mainDocumentPart = doc.MainDocumentPart ?? doc.AddMainDocumentPart();

    // Get the Styles part for this document.
    StyleDefinitionsPart? part = mainDocumentPart.StyleDefinitionsPart;

    // If the Styles part does not exist, add it and then add the style.
    if (part is 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.
    mainDocumentPart.Document ??= new Document();
    mainDocumentPart.Document.Body ??= new Body();

    mainDocumentPart.Document.Body.AppendChild(p);

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

    // Get a reference to the ParagraphProperties object.
    p.ParagraphProperties ??= new ParagraphProperties();
    ParagraphProperties pPr = p.ParagraphProperties;

    // If a ParagraphStyleId object doesn't exist, create one.
    pPr.ParagraphStyleId ??= new ParagraphStyleId();

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

另请参阅