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;
}

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

参考文献:

1\]https://github.com/dotnet/Open-XML-SDK \[2\]https://learn.microsoft.com/zh-cn/office/open-xml/open-xml-sdk

相关推荐
JQLvopkk9 小时前
C# 工业级上位机:交互实战
开发语言·c#·交互
ONLYOFFICE9 小时前
如何将 Word 集成到 Web 应用程序? 5 种方法详解与对比
前端·word·onlyoffice
kingwebo'sZone10 小时前
PdfiumViewer使用权限控制期操作按钮(PdfViewer其实也可以完整兼容)
c#
张小俊_11 小时前
WPF 跨线程 UI 更新与硬编码赋值引发的 Bug 排查
c#·bug·wpf
無斜11 小时前
【CAPL实用开发】--- CAPL调用 .NET DLL
开发语言·c#·capl·canoe
wolfengi11 小时前
python之使用docxtpl渲染word模板
数据库·python·word
puamac11 小时前
UcTabWindow 布局多tab,加载编辑器和资源管理器等自定义控件
c#·编辑器·datagridview
唐青枫12 小时前
别再把增删改查写成一锅粥!C#.NET CQRS 从原理到实战
c#·.net
czhc114007566321 小时前
C# 428 线程、异步
开发语言·c#
唐青枫1 天前
C#.NET ThreadLocal 深入解析:线程独享数据、性能收益与实战边界
c#·.net