C#测试调用OpenXml操作word文档的基本用法

  OpenXML SDK是微软为高效处理Office文档(如Word、Excel)而开发的开源.NET库,它直接操作文档内部的XML结构,无需安装Office软件即可实现文档的创建、读取和编辑,常用于服务器端批量生成报表、自动化文档处理等场景,轻量且跨平台。本文学习基于OpenXML SDK打开word文档查找输入框并插入内容、查找并复制表格的基本用法。
  VS2022创建控制台程序,在Nuget包管理器中搜索并安装DocumentFormat.OpenXml包。

  使用DeepSeek生成带封面和表格的两页文档用于功能测试(实际上生成的是html文件,下载到本地后用word打开又另存为word),如下图所示。

  在word软件的选项中启用开发工具菜单,然后在开发工具菜单栏中使用属性菜单设置封面中输入框的标记,同时通过表格属性设置表格的标题,以便后续通过程序能够查找相应的内容。

  OpenXML SDK中WordprocessingDocument类代表文档对象,使用WordprocessingDocument.Open函数打开word文档,该函数支持通过文件路径或文件流形式打开文档。

  MainDocumentPart、Body、SdtElement 和Table 是处理 Word 文档(.docx)的核心类,下表列出其简要介绍和用途:

类 说明 所在命名空间 常用属性/方法
MainDocumentPart 代表 Word 文档的主文档部分,是操作文档内容的入口点。 DocumentFormat.OpenXml.Packaging Document (获取文档对象), AddNewPart() (添加新部件), GetPartById(String) (通过ID获取部件)
Body 表示 Word 文档的正文,是段落、表格等块级元素的容器。 DocumentFormat.OpenXml.Wordprocessing AppendChild(OpenXmlElement) (添加子元素), Descendants() (获取特定类型的后代元素), Elements() (获取子元素)
SdtElement 代表内容控件(Structured Document Tag),用于创建结构化、可重复使用的文档区域或表单。 DocumentFormat.OpenXml.Wordprocessing Descendants(), SdtProperties (获取内容控件的属性), SdtContentBlock (获取内容块)
Table 表示 Word 文档中的一个表格,由行(TableRow)和单元格(TableCell)组成。 DocumentFormat.OpenXml.Wordprocessing AppendChild(TableRow), TableProperties (表格属性), Descendants()

  基于上述类,打开word文档并获取正文对象的主要代码如下:

csharp 复制代码
Dictionary<string, string> dicTest = new Dictionary<string, string>();
dicTest.Add("filename", "测试文件名称");
dicTest.Add("filecode", "test-file-code-001");
dicTest.Add("createtime", DateTime.Now.ToString());
dicTest.Add("dept", "测试部门");
dicTest.Add("editor", "tom");

WordprocessingDocument doc = WordprocessingDocument.Open(fileStream, true);
MainDocumentPart mainPart = doc.MainDocumentPart;
Body body = mainPart.Document.Body;

  基于标记查找内容控件并输入文本的主要代码如下:

csharp 复制代码
var contentControls = Body.Descendants<SdtElement>();

foreach (var control in contentControls)
{
    // 获取内容控件的标记
    var tag = control.Descendants<Tag>().FirstOrDefault()?.Val?.Value;

    if (tag != null && dicTest.ContainsKey(tag))
    {
        // 找到文本元素并替换内容
        var textElement = control.Descendants<Text>().FirstOrDefault();
        if (textElement != null)
        {
            textElement.Text = dicTest[tag];
        }
    }
}

  查找并辅助表格的主要代码如下所示:

csharp 复制代码
Table targetTable = FindTableByTableTitle(body, tableTitle);
Table clonedTable = (Table)targetTable.CloneNode(true);
body.AppendChild(clonedTable );

private static Table FindTableByTableTitle(Body body, string title)
{
    // 查找所有表格
    var tables = body.Descendants<Table>();

    foreach (var table in tables)
    {
        // 获取表格属性
        var tableProperties = table.Elements<TableProperties>().FirstOrDefault();
        if (tableProperties != null)
        {
            // 获取表格标题
            var tableCaption = tableProperties.Elements<TableCaption>().FirstOrDefault();
            if (tableCaption != null && tableCaption.Val != null && tableCaption.Val.Value.Equals(title, StringComparison.OrdinalIgnoreCase))
            {
                return table;
            }
        }
    }

    return null;
}

  封面内容替换的程序运行效果如下所示,表格复制内容都是相同的,就不再重复截图。

参考文献:

1https://github.com/dotnet/Open-XML-SDK

2https://learn.microsoft.com/zh-cn/office/open-xml/open-xml-sdk

相关推荐
曹牧4 小时前
C#:未被引用的函数
c#
上位机妹子10 小时前
EF Core 两种继承映射:每层次一张表(TPH)与每类型一张表(TPT)
数据库·c#·.netcore·ef core
小羊没烦恼!11 小时前
jQuery1.5的改进细节
java·服务器·开发语言·前端·c#
下页、再停留12 小时前
【C#桌面客户端系列学习-8】批量导出数据为csv格式
开发语言·c#·visual studio
波力海苔夹心脆67513 小时前
C# 视觉检测实战:PLC 按钮触发 VisionPro 检测,OK 亮灯 / NG 灭灯(西门子 PLC,含界面显示与图片存档)
开发语言·经验分享·c#·自动化·视觉检测·.net
weixin_4166600713 小时前
多个 Markdown 文件批量转 Word:PowerShell + Pandoc,连同图片和公式一起检查
word·豆包·deepseek
必须得开心呀13 小时前
为什么 python-docx 打不开加密的 .docx,Word COM 却能打开
python·word
扶风ff14 小时前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word
kim14 小时前
一个人 + AI,用 WinForms 搓了个 376KB 的 Windows 便签:便签 / 截图 / 标注 / OCR / 待办全塞进去了
c#
hez201015 小时前
一行代码在 .NET 项目里启用 Satori GC
c#·.net·.net core·gc·clr