尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

DocumentFormat.OpenXml + MiniWord:Word 文档合并与内容赋值的优雅组合

DocumentFormat.OpenXml + MiniWord:Word 文档合并与内容赋值的优雅组合
📅 发布时间:2026/6/19 15:43:09

在项目开发中,遇到这样的需求:要把一堆数据快速整理成格式规范的Word文档。比如:

  • 人力资源要给新员工批量制作入职通知书
  • 学校老师要为全班同学生成期末成绩单
  • 销售部门要给不同客户发送个性化的报价单
  • 财务人员要定期生成标准格式的统计报表

这些场景都有一个共同特点:数据量大、格式固定、重复性高。查找资料后了解到两个.NET库可以很轻松的就能够解决上述问题:

  • MiniWord(0.9.2):可以根据模板加填充符合快速的填充数据
  • DocumentFormat.OpenXml(3.3.0):可以把多个文档合并成一个

🛠️ 技术栈介绍

MiniWord - 文档内容填充

创建一个Word模板,只需要在需要填数据的地方写上{{姓名}}、{{成绩}}这样的标记,然后把数据扔给MiniWord,它就能自动生成完整的文档。同时还能够填充Image图片、字体颜色、超链接等功能,非常的方便!

DocumentFormat.OpenXml - 微软官方的文档操作工具

这个工具比较专业,能直接操作Word文档的内部结构。我主要用它来做文档合并——把多个小文档拼接成一个大文档,还能自动加上分页符,让每个部分都从新的一页开始。

💻 完整实现代码

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using MiniSoftware;// 生成 100 条随机数据
List<Person> persons = GenerateRandomData(100);// 准备临时目录
string tempDir = "TempDocs";
if (!Directory.Exists(tempDir)) Directory.CreateDirectory(tempDir);string tplPath = "template.docx";   // MiniWord 模板// 每 10 人一组
int groupSize = 10;
int groupCount = (int)Math.Ceiling(persons.Count / (double)groupSize);
var groupFiles = new List<string>(groupCount);for (int g = 0; g < groupCount; g++)
{// 当前 10 人var group = persons.GetRange(g * groupSize,Math.Min(groupSize, persons.Count - g * groupSize));// 构建表格行var rows = new List<Dictionary<string, object>>();foreach (var p in group){rows.Add(new Dictionary<string, object>{["Id"] = p.Id,["Name"] = p.Name,["Age"] = p.Age,["City"] = p.City,["Email"] = p.Email,["Score"] = p.Score});}// 模板变量var dict = new Dictionary<string, object>{["GroupNo"] = g + 1,["Persons"] = rows          // MiniWord 支持集合标签 {{Persons}}};string groupPath = Path.Combine(tempDir, $"Group_{g + 1}.docx");MiniWord.SaveAsByTemplate(groupPath, tplPath, dict);groupFiles.Add(groupPath);
}// 4. 合并所有组文件
string finalPath = "成绩单_总.docx";
MergeWordDocuments(groupFiles.ToArray(), finalPath);Console.WriteLine($"完成!共 {groupCount} 个组(每组 10 人),已合并为 {finalPath}");
Console.ReadKey();// 生成 n 条随机数据
static List<Person> GenerateRandomData(int n)
{var list = new List<Person>(n);var rnd = new Random(Guid.NewGuid().GetHashCode());string[] cities = { "北京", "上海", "广州", "深圳", "成都", "杭州", "西安", "武汉", "南京", "重庆" };string[] firstNames = { "王", "李", "张", "刘", "陈", "杨", "赵", "黄", "周", "吴" };string[] lastNames = { "伟", "芳", "娜", "敏", "静", "丽", "强", "磊", "洋", "勇" };for (int i = 1; i <= n; i++){string name = firstNames[rnd.Next(firstNames.Length)] +lastNames[rnd.Next(lastNames.Length)] +(rnd.Next(2) == 0 ? lastNames[rnd.Next(lastNames.Length)] : "");int age = rnd.Next(18, 66);string city = cities[rnd.Next(cities.Length)];string email = $"{name.ToLower()}@example.com";double score = Math.Round(rnd.NextDouble() * 100, 1);list.Add(new Person{Id = i,Name = name,Age = age,City = city,Email = email,Score = score});}return list;
}// 合并Word文档
static void MergeWordDocuments(string[] sourcePaths, string outputPath)
{using (WordprocessingDocument mergedDoc =WordprocessingDocument.Create(outputPath, WordprocessingDocumentType.Document)){// 创建文档主体MainDocumentPart mainPart = mergedDoc.AddMainDocumentPart();mainPart.Document = new Document(new Body());for (int i = 0; i < sourcePaths.Length; i++){string sourcePath = sourcePaths[i];if (!File.Exists(sourcePath)){throw new FileNotFoundException($"文件不存在: {sourcePath}");}// 复制源文档内容using (WordprocessingDocument sourceDoc =WordprocessingDocument.Open(sourcePath, false)){Body sourceBody = sourceDoc.MainDocumentPart.Document.Body;foreach (OpenXmlElement element in sourceBody.ChildElements){mainPart.Document.Body.AppendChild(element.CloneNode(true));}}// 如果不是最后一个文档,添加分页符if (i < sourcePaths.Length - 1){mainPart.Document.Body.AppendChild(new Paragraph(new Run(new Break() { Type = BreakValues.Page })));}}mainPart.Document.Save();}
}class Person
{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public string City { get; set; }public string Email { get; set; }public double Score { get; set; }
}

📝 模板设计

要使用 MiniWord,需要创建一个模板文档 template.docx。在模板中,我们可以使用简单的标记语法:

第 {{GroupNo}} 组学生成绩单

Id 姓名 年龄 城市 邮箱 成绩
{{Persons.Id}} {{Persons.Name}} {{Persons.Age}} {{Persons.City}} {{Persons.Email}} {{Persons.Score}}

🔍 技术要点解析

MiniWord 数据绑定

// 构建表格数据
var rows = new List<Dictionary<string, object>>();
foreach (var p in group)
{rows.Add(new Dictionary<string, object>{["Id"] = p.Id,["Name"] = p.Name,// ... 其他属性});
}// 使用模板生成文档
var dict = new Dictionary<string, object>
{["GroupNo"] = g + 1,["Persons"] = rows
};
// 主要部分
MiniWord.SaveAsByTemplate(groupPath, tplPath, dict);

DocumentFormat.OpenXml 文档合并

// 创建目标文档
using (WordprocessingDocument mergedDoc = WordprocessingDocument.Create(outputPath, WordprocessingDocumentType.Document))
{MainDocumentPart mainPart = mergedDoc.AddMainDocumentPart();mainPart.Document = new Document(new Body());// ...省略// 逐个复制源文档内容foreach (OpenXmlElement element in sourceBody.ChildElements){mainPart.Document.Body.AppendChild(element.CloneNode(true));}// ...省略// 添加分页符mainPart.Document.Body.AppendChild(new Paragraph(new Run(new Break() { Type = BreakValues.Page })));
}

相关资源:

  • MiniWord GitHub仓库
  • DocumentFormat.OpenXml GitHub仓库
  • 阅读原文

相关新闻

  • 【学习笔记】回文自动机初步总结
  • rest_framework框架视图集整理
  • SPP question regarding Issues Due To Gaming Spoofers

最新新闻

  • 嵌入式指令压缩技术:MPC562/564硬件解压原理与工程实践
  • Mission Planner:从新手到专家的无人机飞行控制完全指南
  • AI Coding工具链协同实战:CLAUD+OpenClaw+GLM-5集成指南
  • 嵌入式开发中sbrk、unlink、write系统调用的底层原理与实战优化
  • KL82微控制器功耗与时钟系统深度解析与低功耗设计实战
  • PEEK转子生产商价格透明测评,2026实力口碑榜不踩坑 - 工业品牌热点

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号