创建段落样式并将其添加到字处理文档
本主题演示如何使用 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 时,该行为提供将自动应用于下一段落的段落样式。
样式分别使用 pPr 和 rPr 元素指定段落级别和字符级别的属性。 在这种情况下,连续文本属性是应用于段落中的每段连续文本的属性集。
然后,会通过在段落属性 (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;
}