使用 OpenXML 和 C# 创建 Word 表格,无需自动化/互操作





5.00/5 (7投票s)
本文帮助您在不使用互操作对象的情况下使用 OpenXML 创建 Word 表格。
引言
欢迎再次来到 OpenXML 世界,在这里你可以借助 C# 和 OpenXML 创建 Word 表格。
这里的奇妙之处在于,无需在你的机器上安装 Word,也无需互操作对象。让我们看看如何实现它
背景
我在之前的文章中简要解释了“什么是 Open XML”,如果你是 OpenXML 的新手,请查看此链接
https://codeproject.org.cn/Tips/994905/Edit-Word-Documents-using-OpenXML-and-Csharp-Witho
OpenXML 表格结构
在人们看来,OpenXML 冗长而复杂,但如果你理解它的结构,那么它就真的易如反掌。所以让我们首先从表格结构开始。
在了解 OpenXML 之前我们需要准备的东西
OpenXML 表格入门
表格由行和单元格组成,结构与 HTML 表格非常相似。它由 <w:tbl> 元素定义。基本表格结构可以定义为
<w:tbl>
<w:tblpr>.....</w:tblpr>
<w:tblgrid>....</w:tblgrid>
<w:tr>....</w:tr>
</w:tbl>
在上述结构中我们可以看到,表格有三个主要标签。
1. w:tblpr : 指定表格的全局属性。这些属性可以被单独的表格级别覆盖
2. w:tblgrid : 指定表格的列
3. w:tr : 指定一个表格行
让我们详细地逐一查看它们
1. w:tblpr
这指定了表格的全局属性,每个属性都是 <tblPr> 的子元素,它们影响表格中的所有行和单元格,但样式可以被每个单独的行、列或单元格覆盖。
最常用的属性如下所示
属性名称 | 描述 |
---|---|
w:jc | 表示表格对齐方式。 |
w:shd | 表示表格底纹。 |
w:Borders | 表示表格边框。 |
w:Caption | 表示表格标题。 |
w:CellMar | 表示表格单元格边距。 |
w:tblCellSpacing | 表示表格间距。 |
w:tblLayout | 表示表格布局。 |
w:tblLook | 表示表格条件格式。 |
请参见下面的标签片段
<w:tblPr> <w:tblStyle w:val="TestTableStyle"/> <w:jc w:val="center"/> </w:tblPr>
2. w:tblgrid
表格的列由 <w:tblGrid> 元素定义,它包含属性 <w:gridCol> ,表示每列的大小,如果表格有 4 列,则 w:tblgrid 有 4 个 w:gridCol 标签
请参见下面的标签片段
<w:tblGrid> <w:gridCol w:w="2800"/> <w:gridCol w:w="2600"/> <w:gridCol w:w="2800"/> <w:tblGrid>
3.w:tr
这是行定义标签,它是表格的核心元素。它有以下子集
属性名称 | 描述 |
---|---|
w:trPr | 表示行级别属性,但可以被单个单元格覆盖 |
w:tblPrEx | 表示行的表格属性,这些属性通常用于旧版文档以及两个独立表格合并的情况 |
w:tc | 表示单个表格单元格。 |
请参见下面的标签片段
<w:tr>
<w:trPr>.....</w:trPr>
<w:tblPrEx>....</w:tblPrEx>
<w:tc>....</w:tc>
</w:tr>
现在我们将深入探讨 w:tr 属性。
3.1 w:trPr
此元素表示行级别属性,每个属性都是 <trPr> 的子元素,它们影响行中的所有单元格。最常用的属性如下所示
属性名称 | 描述 |
---|---|
w:cantSplit | 它通过将行的起始位置移动到新页的起始位置,防止行内容跨多页断开,它有助于行在新页开始 |
w:hidden | 有助于隐藏整行 |
w:jc | 指定行的对齐方式 |
w:tblCellSpacing | 指定单元格间距,它与 HTML 表格属性相同 |
w:tblHeader | 指定当前行应在新页上作为每个表格的标题重复 |
w:trHeight | 表示行的高度,如果可选,则高度将自动调整 |
3.2 w:trPrEx
如所述,表格的特殊属性,借助此属性我们可以显示具有特定例外的任何行。w:trPrEx 具有与 <w:trPr> 几乎相同的属性,一些新属性如下所示
属性名称 | 描述 |
---|---|
w:shd | 指定背景颜色,它是可选属性,它有不同的属性,如 color、fill、val。 |
w:tblBorders | 指定行边框 |
w:tblCellMar | 指定单元格的边距,这基本上是特殊行的单元格属性(我们将在单元格部分详细查看此属性) |
w:tblInd | 在行的前沿之前,它会向行添加缩进, |
w:tblLayout | 指定内置表格布局 |
w:tblLook | 指定 Word 应用程序指定的内置表格布局 |
请参见下面的标签片段
<w:tr> <w:tblPrEx> <w:tblBorders> <w:top w:val="single" w:sz="12" w:space="0" w:color="FF0000" /> <w:start w:val="single" w:sz="24" w:space="0" w:color="00FF00" /> <w:bottom w:val="single" w:sz="12" w:space="0" w:color="0000FF" /> <w:end w:val="single" w:sz="24" w:space="0" w:color="000000" /> <w:insideH w:val="single" w:sz="24" w:space="0" w:color="FFFF00" /> <w:insideV w:val="single" w:sz="24" w:space="0" w:color="FF00FF" /> </w:tblBorders> </w:tblPrEx> </w:tr>
3.3 w:tc
此标签指定单个表格单元格的数据,这些标签嵌套在表格行标签下。w:tc 的核心元素如下
属性名称 | 描述 |
---|---|
w:p | 指定每个单元格的段落 |
w:tbl | 指定表格作为单元格的内容 |
w:tcPr | 指定要应用于当前单元格的属性。 |
请参见下面的片段
<w:tc> <w:tcPr> <w:tcW w:w="2600" w:type="dxa"/> </w:tcPr> <w:p> <w:r> <w:t>cell content</w:t> </w:r> </w:p> </w:tc>
上面的标记片段包含表格单元格,其中段落 (<w:p>)、运行 (<w:p>)、文本 (<w:r>) 是单元格的子元素。
3.3.1 w:p
段落是单元格的主要部分,段落可以包含段落的丰富格式属性,段落还可以包含书签、超链接、字段、注释等。段落的核心元素是属性 (<w:pPr>) 和运行 (<w:r>)
段落属性和运行都有自己的属性,如段落框架、缩进、对齐、编号、边框、段落样式、底纹和制表符。
请参见下面的标记
<w:p> <w:pPr> <w:pStyle> w:val="TestWeb"/> <w:spacing w:before="20" w:after="20"/> </w:pPr> <w:r> <w:t>This is cell content</w:t> </w:r> </w:p>
3.3.2 w:tcPr
tcPr 表示单元格属性,这些属性用于装饰单元格。行和列属性可以在此部分中被覆盖
属性名称 | 描述 |
---|---|
w:gridSpan | 指定单元格跨行 |
w:hideMark | 指定隐藏表格单元格标记的末尾 |
w:noWrap | 指定防止文本换行,它是布尔属性 |
w:tcBorders | 指定表格单元格边框 |
w:tcFitText | 指定单元格内的文本可以扩展到单元格的宽度,这是布尔属性 |
w:tcMar | 指定表格单元格边距 |
w:tcW | 指定表格单元格宽度 |
w:vAlign | 指定表格单元格垂直对齐方式 |
w:vMerge | 此属性指示单元格是否是合并组单元格的一部分,它有两个可能的值:continue 和 restart |
3.3.1.1 w:r
运行定义文本属性。最常见的运行只包含文本,但它可能包含符号、制表符、连字符、回车符、图画、换行符和脚注引用等内容
请参见运行元素的以下属性
属性名称 | 描述 |
---|---|
w:br | 指定一个换行符,例如 <w:br/> |
w:cr | 指定一个回车符 |
w:drawing | 指定 DrawingML 对象在文档中的布局 |
w:noBreakHypen | 指定不间断连字符。 |
w:rPr | 指定运行的属性,例如 |
w:softHypen | 指定 Word 应用程序指定的内置表格布局 |
w:sym | 指定一个特殊字符或符号 |
w:t | 指定将在单元格中显示的实际文本,这是表格标记中非常重要和核心的元素,此元素保存实际文本内容。 |
w:tab | 指定 TAB 字符 |
请参见下面的标记片段
<w:r> <w:rPr> <w:b/> <w:i/> </w:rPr> <w:t>This is sample text</w:t> </w:r>
3.3.1.1.1 w:rPr
此元素包含运行的不同属性,然后应用于 <w:t> 部分中存在的实际文本
以下是运行最常用的属性
属性名称 | 描述 |
---|---|
w:b | 以粗体显示文本,存在于文本元素中,例如 <w:b /> |
w:i | 以斜体显示文本,存在于文本元素中,例如 <w:i /> |
w:caps | 以小写或大写显示文本,取决于 'val' 属性,例如 <w:caps w:val="true" /> |
w:color | 以指定颜色显示文本,它接受颜色代码作为颜色,例如 <w:color w:val="FF1244" /> |
w:dstrike | 以删除线格式显示文本,例如 <w:dstrike w:val="true"/> |
w:emboss | 以浮雕样式显示文本,例如 <w:emboss w:val="true" /> |
w:imprint | 以压痕样式显示文本,例如 <w:imprint w:val="true"/> |
w:outline | 以轮廓样式显示文本,例如 <outline w:val="true"/> |
w:rStyle | 根据样式 ID 显示字符样式(此处样式是内置的) |
w:shadow | 显示文本对每个字符都有阴影 <w:shadow w:val="true"/> |
w:smallCaps | 以小型大写字母显示文本,caps 和 smallCaps 的区别在于,caps 使文本大小更大并将文本转换为大写,而 smallCaps 将文本转换为大写但不会增加字体大小,例如 <w:smallCaps w:val="true"/> |
w:sz | 以指定大小显示文本,例如 <w:sz w:val="14"/> . |
w:u | 以下划线显示文本,例如 <w:u w:val="double"/> |
w:vanish | 此元素中的文本将隐藏不显示,例如 <vanish/> |
w:vertAlign | 以上标或下标显示文本,例如 <vertAlign w:val="superscript | baseline | subscript "/> |
所以这是 OpenXML 表格格式的原始层次结构
使用标记和代码
现在,有了上述所有标记,我们可以在 Word (DOCX) 文件中创建一个表格,在这里我开发了一个小应用程序,它将在 Word 文件中放置一个漂亮的表格
首先创建表格属性,请参阅下面的 XML 标记(我们已应用内置表格样式和外观作为 Accept4)
<w:tblPr>
<w:tblStyle w:val="LightGrid-Accent4" />
<w:tblW w:w="0" w:type="auto" />
<w:tblLook w:val="04A0" />
</w:tblPr>
然后我们将向表格中添加列,请参阅下面的 XML 标记(我们已取 3 列)
<w:tblGrid>
<w:gridCol w:w="2394" />
<w:gridCol w:w="2394" />
<w:gridCol w:w="2394" />
</w:tblGrid>
现在我们将向其中添加带有要显示的文本的行。(我们在此处添加了 1 行,包含 3 个单元格)
<w:tr w:rsidR="004D1DA5" w:rsidTr="004D1DA5"> <w:trPr> <w:cnfStyle w:val="100000000000" /> </w:trPr> <w:tc> <w:tcPr> <w:cnfStyle w:val="001000000000" /> <w:tcW w:w="2394" w:type="dxa" /> <w:hideMark /> </w:tcPr> <w:p w:rsidR="004D1DA5" w:rsidRDefault="004D1DA5"> <w:pPr> <w:jc w:val="center" /> </w:pPr> <w:r> <w:t>No</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="2394" w:type="dxa" /> <w:hideMark /> </w:tcPr> <w:p w:rsidR="004D1DA5" w:rsidRDefault="004D1DA5"> <w:pPr> <w:jc w:val="center" /> <w:cnfStyle w:val="100000000000" /> </w:pPr> <w:r> <w:t>Name</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="2394" w:type="dxa" /> <w:hideMark /> </w:tcPr> <w:p w:rsidR="004D1DA5" w:rsidRDefault="004D1DA5"> <w:pPr> <w:jc w:val="center" /> <w:cnfStyle w:val="100000000000" /> </w:pPr> <w:r> <w:t>Sex</w:t> </w:r> </w:p> </w:tc> </w:tr>
这是创建标记的代码
# 创建表格对象并添加表格属性
//create table object
Table table1 = new Table();
//define table properties
TableProperties tableProperties1 = new TableProperties();
TableStyle tableStyle1 = new TableStyle() { Val = "LightGrid-Accent4" };
TableWidth tableWidth1 = new TableWidth() { Width = "0", Type = TableWidthUnitValues.Auto };
TableLook tableLook1 = new TableLook() { Val = "04A0" };
//add table styles to properties
tableProperties1.Append(tableStyle1);
tableProperties1.Append(tableWidth1);
tableProperties1.Append(tableLook1);
# 定义表格列并将它们添加到表格中
//create and define new table columns
TableGrid tableGrid1 = new TableGrid();
GridColumn gridColumn1 = new GridColumn() { Width = "2394" };
GridColumn gridColumn2 = new GridColumn() { Width = "2394" };
GridColumn gridColumn3 = new GridColumn() { Width = "2394" };
//add columns in table
tableGrid1.Append(gridColumn1);
tableGrid1.Append(gridColumn2);
tableGrid1.Append(gridColumn3);
# 定义新的单元格对象及其关联的段落、运行、文本对象以及它们各自的属性。
//create table row object
TableRow tableRow1 = new TableRow(){RsidTableRowAddition="004D1DA5",RsidTableRowProperties="004D1DA5"};
//create row properties
TableRowProperties tableRowProperties1 = new TableRowProperties();
ConditionalFormatStyle conditionalFormatStyle1 = new ConditionalFormatStyle(){Val="100000000000"};
tableRowProperties1.Append(conditionalFormatStyle1);
//create cell object and its properties
TableCell tableCell1 = new TableCell();
TableCellProperties tableCellProperties1 = new TableCellProperties();
ConditionalFormatStyle conditionalFormatStyle2 = new ConditionalFormatStyle(){Val="001000000000"};
TableCellWidth tableCellWidth1 = new TableCellWidth(){Width="2394",Type=TableWidthUnitValues.Dxa};
HideMark hideMark1 = new HideMark();
tableCellProperties1.Append(conditionalFormatStyle2);
tableCellProperties1.Append(tableCellWidth1);
tableCellProperties1.Append(hideMark1);
//create paragrpah object and its properties
Paragraph paragraph1 = new Paragraph(){RsidParagraphAddition="004D1DA5",RsidRunAdditionDefault="004D1DA5"};
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
Justification justification1 = new Justification() { Val = JustificationValues.Center };
paragraphProperties1.Append(justification1);
//create Run and Text
Run run1 = new Run();
Text text1 = new Text();
//add content in Text
text1.Text = "No";
//add Text to Run
run1.Append(text1);
//add Run to paragraph
paragraph1.Append(paragraphProperties1);
paragraph1.Append(run1);
//add Paragraph to cell
tableCell1.Append(tableCellProperties1);
tableCell1.Append(paragraph1);
是的,我们已经完成了代码,现在尝试测试它。
总结
OpenXML 是一个开放的国际标准,ECMA-376 第二版和 ISO/IEC 29500 标准,它们基于 XML 和 ZIP 等技术。您可以借助 OpenXML 提高应用程序性能,开发人员无需打开 DOCX 文件即可与其交互。借助 OpenXML,您只需几行代码即可执行复杂操作。
在本文中,我们已经看到了如何使用 OpenXML 和 C# 绘制 Word 表格
在更多的事情发生和学习之前,我们将在本文的后续版本中看到更多好的示例。
欢迎提出建议和疑问。
谢谢
koolprasad2003