简介:C#DocX 源码与 Demo 资源包,面向需要在 .NET 环境中操作 Word 文档的开发者,解决不安装 Microsoft Office 也能完成 Word 创建、编辑与 PDF 转换的需求。压缩包内含 244 个文件,以 83 个 C# 源码文件、86 个 Word 示例文档、7 个 DLL 动态库为核心,并附带工程配置文件、签名文件、图片及说明文档,整体约 4.93MB,目录结构清晰;其中 docx 文件可作为输入输出样例,sln/csproj 工程文件便于用 Visual Studio 直接打开编译。示例工程覆盖创建文档、编辑段落与表格、页眉页脚设置、模板替换、内容替换、表格尺寸调整及 PDF 转换等高频应用场景,Xceed.Document.NET.dll 和 Xceed.Words.NET.dll 均包含在内,并配有详细注释,亲测可运行,能帮助 .NET 开发者快速落地 Word 自动化处理任务。无论是初学者了解 Word 文档对象模型,还是中高级开发者实现服务器端批量生成报表、合同或导出 PDF,都可以从这套源码与示例中直接提取可复用代码。当前已有 272 人学习下载,整体内容完整、可用性强,适合作为自动化报告编辑、在线文档处理等项目的参考基础。 C# 处理 Word 文档,我用 DocX 库做了一套可直接上手的方案
做 C# 开发这几年,处理 Word 文档一直是绕不开的环节。早些年我用 Microsoft.Office.Interop.Word,但那玩意儿依赖 Office COM 组件,服务器上没装 Office 就是一场灾难,部署一次要折腾半天。后来换成 Aspose.Words,功能是强,可授权费用对个人项目来说确实不太友好。直到我遇到 DocX 这个库,才真正感觉找到了写 Word 文件的正确姿势。
最近我把一套「C# DocX 源码 + demo」整理了出来,里面包含了完整的 Xceed.Document.NET.dll 和 Xceed.Words.NET.dll,自己亲身验证过,可以直接拿来用。这篇文章我不打算写那种读起来像说明书的东西,我只想把这些年用 DocX 在真实项目里踩过的坑、验证过的写法、以及怎么把这套源码快速塞进你自己项目里,一次交代清楚。
1. 为什么是 DocX,而不是 Interop 或 Aspose
先说个大多数新手都会掉的坑:一提到操作 Word,第一反应就是打开 Visual Studio,添加引用,然后开始写 Interop。但这东西本质上是在你程序外面启动一个 Word 进程。如果部署环境是 Windows Server,而且是最小化安装,压根就没有 Word,你的程序一跑就报错。而且 COM 进程回收不及时,IIS 里跑一会儿就会出现内存暴涨。
Aspose.Words 没这个问题,它是纯托管代码,功能也强大。但正版授权不便宜,很多小公司和个人开发者舍不得花这个钱,最后就用了破解版,心里又总觉得不踏实。
DocX 的优势刚好卡在两者中间。
我用一个表格说明它的定位:
| 维度 | Interop | Aspose.Words | DocX |
|---|---|---|---|
| 依赖 Office 环境 | 是 | 否 | 否 |
| 收费 | 免费但费运维 | 商业授权 | 免费开源(含商业授权选项) |
| 学习成本 | 高(COM 对象模型复杂) | 中 | 低(API 直观) |
| 常用功能覆盖 | 全 | 全 | 约 80% |
| 生成速度 | 慢 | 快 | 最快 |
看到这你大概能理解为什么我最终选择 DocX。它不是万能的,但是覆盖日常 80% 的文档创建和编辑场景绰绰有余。像合同套打、批量生成报告、导出数据表这种需求,用 DocX 写起来非常顺手。而且它在生成文档时不吃内存,速度是真的快,我这套 demo 里有一个批量生成 500 份合同的测试,耗时表现相当亮眼。
2. 源码结构和运行环境说明
这份源码我按照"拿来即用"的标准整理过。解压后你会看到两个核心 DLL 文件,Xceed.Document.NET.dll 和 Xceed.Words.NET.dll,这两个文件都是编译好的、可以直接引用的托管程序集,不需要额外安装任何 SDK。
源码目录概括来说是这样的:
DocXDocs/:WinForms 演示工程,直接打开运行DocXCore/:控制台演示工程,适合研究逻辑libs/:两个 DLL 的存放目录docs/:DocX 官方文档翻译笔记samples/:生成的示例 Word 文件
开发环境我建议你用 Visual Studio 2019 或 2022,.NET Framework 4.6.1 以上都可以。我自己测试用的是 .NET Framework 4.7.2,跑起来完全没有问题。如果你想用 .NET Core 或者 .NET 5/6,也没问题,DocX 是支持跨平台的,只是你在引用 DLL 时需要稍微留意下目标框架的兼容性。
一个重要的提示:这两个 DLL 不是我自己编译的,也不是破解版,是 DocX 官方开源项目的发布版本。Xceed 公司收购 DocX 后继续维护,开源部分依然可以免费使用,商用的话建议查看最新的授权条款,但这个版本用于学习和内部工具开发完全够用。
3. 核心功能实操拆解:从创建文档到复杂排版
我一直认为,只看不练等于白搭。这一节我直接给代码、给注释、给效果,你现在可以打开 Visual Studio 建一个控制台项目,然后跟我一步一步跑。
3.1 环境准备:创建工程和引用 DLL
新建一个控制台工程后,先在解决方案里建一个libs文件夹,把两个 DLL 复制进去。然后右键项目选择"添加引用",点击"浏览"定位到这两个文件确认引用。
等一下,这里有第一个坑要提醒你:这两个 DLL 都依赖System.IO.Packaging。在 .NET Framework 项目里,你需要添加WindowsBase程序集的引用,否则运行时会报"找不到类型 Document"之类的错误。这个错误很隐蔽,因为编译阶段不报,运行才炸。
正确步骤是:
1. 右键"引用" -> "添加引用" 2. 在程序集列表里勾选 WindowsBase 3. 确认两个 DLL 已引用 4. 编译运行如果你是用 .NET Core 或 .NET 5+,WindowsBase默认已经包含,不需要额外处理。
3.2 快速生成第一个 Word 文档
引用好之后,在 Program.cs 里先把命名空间using Xceed.Document.NET;和using Xceed.Words.NET;加上。DocX 的核心入口是DocX.Create(),我经常用如下方式创建文档:
using (var document = DocX.Create(@"D:\test.docx")) { // 插入带格式的段落 var title = document.InsertParagraph("DocX 实战测试"); title.FontSize(16f).Bold().Color(Color.Red); title.Alignment = Alignment.center; // 插入正文 var content = document.InsertParagraph("这是使用 Xceed.Words.NET 生成的文档内容。"); content.FontSize(12f); document.Save(); }这段代码跑完,你会在 D 盘得到一个 test.docx。用 Word 打开,你会看到居中的红色大标题和常规正文。你别小看这两行代码,这里面其实埋了非常核心的 API 设计思路:InsertParagraph返回Paragraph对象,然后通过链式调用设置格式。这种写法贯穿 DocX 所有功能,你学会这一个,基本就学会了一半。
3.3 格式化:字体、颜色、对齐、间距
做正式文档免不了要调整格式,DocX 提供了还算齐全的Paragraph格式属性。像合同标题要居中、正文要首行缩进、重点语句要加粗这些,代码写起来一气呵成:
var para = document.InsertParagraph(); para.Append("这是一段演示文本") .Font("微软雅黑") .FontSize(12f) .Color(Color.Black) .Bold(); para.Alignment = Alignment.left; para.IndentFirstLine = 20f; // 首行缩进,单位是磅 // 行距设置 para.LineSpacing = 1.5f;有一个特别关键的地方:Font("微软雅黑")这个方法的参数是字体名称字符串,在document.InsertParagraph()之后还不会立刻生效,要等到Append()返回的文本对象上调用才有效。这和普通文本编辑器里"先选中文字再设置字体"是一个逻辑,不是设置整个段落的默认字体。
3.4 段落与分页控制
写报告的时候,经常需要在每一章结束后插入分页符。DocX 的做法是document.InsertSectionPageBreak(),这样下一章会另起一页。这个方式比连续回车盖页面要干净得多,而且不会因为字体大小变化导致排版错乱。
还有一个很实用的功能:段前段后间距。写作时为了避免"标题直接顶着上一段文字"的拥挤感,你可以这样操作:
var heading = document.InsertParagraph("第二章 项目背景"); heading.SpacingBefore(12f); // 段前间距 heading.SpacingAfter(6f); // 段后间距这套 API 的命名逻辑是SpacingBefore和SpacingAfter,参数单位是磅。你配合标题样式的字号,调一版之后文档层次感会好很多,不需要过度美化就足够正式。
3.5 插入图片和表格:搞定数据报表
工作中最常用的无非是往报告里插图表和表格。DocX 对图片和表格的支持虽然不算很重,但基本场景都能覆盖。
插入图片的代码:
var image = document.AddImage(@"C:\chart.png"); var picture = image.CreatePicture(300, 150); // 宽度 300px,高度 150px var paragraph = document.InsertParagraph(); paragraph.AppendPicture(picture); paragraph.Alignment = Alignment.center;这里CreatePicture的两个参数分别代表图片显示宽度和高度,单位是像素。如果你不传参数,就按图片原始尺寸插入。我建议尽量传参限制尺寸,尤其在批量自动化出报告时,图片原始尺寸参差不齐会导致整个文档忽长忽短。
表格稍微复杂一点,我直接给一个创建三行三列表格的完整例子:
var table = document.AddTable(3, 3); table.Design = TableDesign.LightGridAccent1; // 指定内置表格样式 table.Rows[0].Cells[0].Paragraphs[0].Append("产品"); table.Rows[0].Cells[1].Paragraphs[0].Append("销量"); table.Rows[0].Cells[2].Paragraphs[0].Append("占比"); // 给单元格填充数据 for (int row = 1; row < 3; row++) { table.Rows[row].Cells[0].Paragraphs[0].Append($"产品{row}"); table.Rows[row].Cells[1].Paragraphs[0].Append($"{row * 100}"); table.Rows[row].Cells[2].Paragraphs[0].Append($"{row * 10}%"); } document.InsertTable(table);TableDesign枚举里自带几十种 Word 内置表格样式。你不需要自己画边框、调底色,指定一个 Design 属性就能获得还不错的视觉效果。这一点在自动生成周报或数据分析时很有用。
3.6 页面设置与页眉页脚
生成正式文档还有一个绕不开的部分:页眉页脚和页面大小。比如合同要 A4 纸、上边距 3 厘米、下边距 2.5 厘米、中间带页码,这些操作在 Interop 里要写一长串代码,DocX 的做法是:
document.MarginTop = 60f; // 单位是磅,1 厘米约等于 28.35 磅 document.MarginBottom = 50f; document.MarginLeft = 50f; document.MarginRight = 50f; // 页脚插入页码 document.AddFooters(); var footer = document.Footers.odd; var pagePara = footer.InsertParagraph(); pagePara.Append("第 "); pagePara.AppendPageNumber(PageNumberFormat.normal); pagePara.Append(" 页");我自己用的时候,比较常用Footers.odd来操作奇偶页页脚。如果你希望首页不显示页码,需要设置document.DifferentFirstPage = true;然后单独留空首页页脚。这个细节很多做了多年 Word 自动化的人都不一定能一次写对。
4. 进阶实战:批量替换与模板生成
基础功能跑通之后,我重点说说模板替换。这是 DocX 在真实项目中价值最大的功能点,也是我整套源码里最核心的演示部分。
4.1 文本占位符替换原理
DocX 支持通过document.ReplaceText()方法批量替换文本占位符。原理很简单,比如你在模板 Word 里写了{客户名称},然后在 C# 代码中使用真实数据替换掉它。这个方法天然适合合同套打、报价单生成、通知书打印这类场景。
需要注意的前提是:模板文件本身必须是.docx格式,而且占位符要写在同一个段落里,不能跨段落。否则 ReplaceText 会匹配不到。
4.2 表格模板循环填充
文本替换只是第一步,真正让效率起飞的是表格循环填充。你可以在模板中放置一行示例数据行,然后通过代码复制行来生成数据列表。但 DocX 没有直接复制的 API,我常用的方案是提前准备一个足够行数的空表,然后循环写入数据。
我这里整套 demo 有一个较完整的例子,核心逻辑大致是:
public static void GenerateContract(string templatePath, string outputPath, List<ContractItem> items, ContractInfo contract) { using (var document = DocX.Load(templatePath)) { // 替换文本占位符 document.ReplaceText("{合同编号}", contract.ContractNo); document.ReplaceText("{甲方名称}", contract.PartyA); document.ReplaceText("{乙方名称}", contract.PartyB); document.ReplaceText("{合同金额}", contract.Amount.ToString("N2")); document.ReplaceText("{签署日期}", contract.SignDate.ToString("yyyy年MM月dd日")); // 表格数据填充 var table = document.Tables[0]; // 假定第一个表格是商品明细表 int dataRowStart = 1; // 表头之后开始 for (int i = 0; i < items.Count; i++) { var row = table.Rows[dataRowStart + i]; row.Cells[0].Paragraphs[0].Append(items[i].Name); row.Cells[1].Paragraphs[0].Append(items[i].Quantity.ToString()); row.Cells[2].Paragraphs[0].Append(items[i].UnitPrice.ToString("N2")); row.Cells[3].Paragraphs[0].Append(items[i].TotalPrice.ToString("N2")); } document.SaveAs(outputPath); } }这段代码跑起来后,你会得到一份完整的合同。里面甲方乙方信息、合同金额、日期、商品清单都填充完毕。用这种方式,几十份合同的生成也就是几秒钟的事。
4.3 多文档合并
还有一个很实用的技巧:把多个 Word 文档合并成一个。比如月度报告需要把几个分部门的报告汇总起来。
using (var mergedDoc = DocX.Create(@"D:\merged.docx")) { foreach (var file in Directory.GetFiles(@"D:\reports\", "*.docx")) { var sourceDoc = DocX.Load(file); foreach (var paragraph in sourceDoc.Paragraphs) { mergedDoc.InsertParagraph(paragraph.Text); } } mergedDoc.Save(); }这段代码有一个明显的局限:它只会保留段落文本,里面图片和表格会丢失。如果只是合并纯文本报告,够了。但如果你需要更复杂的合并,需要遍历源文档中的Images和Tables集合并逐个添加。我在源码的MergeHelper.cs文件里写了完整的合并逻辑,你可以直接参考。
5. 常见问题与排查技巧实录
操作 DocX 的过程中,我踩过不少坑,也总结了一些定位问题的经验。下面整理成一张速查表,方便你按图索骥。
| 现象 | 原因 | 解决方案 |
|---|---|---|
| 编译提示找不到 Document 类型 | 缺少 WindowsBase 引用 | 添加引用勾选 WindowsBase |
| 打开文档提示"内容有问题" | 手动改过 docx 的内部 XML | 使用 DocX.Save() 而不是 SaveAs 覆盖源文件 |
| 中文乱码 | 字体名称拼写错误或系统没有该字体 | 使用系统已装字体名,如"微软雅黑" |
| 替换文本无效 | 占位符跨段落或格式不一致 | 确保占位符在同一页面、同一段落,不加粗不斜体 |
| 表格行数不足 | 预置行数小于数据量 | 动态添加行,使用 table.AddRow() |
| 保存后文件损坏 | 文档被外部进程占用 | 确保没有用 Word 打开该文件,使用 using 释放 |
| 生成大量文档时内存涨 | 未释放 COM 对象或大图未释放 | 每次 Create/Load 都使用 using 块或手动 Dispose |
再说几个容易忽略的操作细节:
DocX 的
Save()和SaveAs()有区别。Save()直接覆盖当前打开的文件,SaveAs()另存到新路径。在模板替换场景中,正确思路是DocX.Load(templatePath)之后,用SaveAs(outputPath)输出到目标路径,不要直接Save()把模板覆盖掉。一旦模板被覆盖,下次再想生成就得重新解压源码。替换模板时,如果模板中含有很多图片或复杂排版,
ReplaceText的速度会明显下降。这时建议把文本替换放在最后执行,先处理表格和图片,再进行替换操作。用
InsertParagraph插入大量文本时,如果一次插入上万字,性能还算能接受。但如果是要逐行插入几万行数据,建议你先拼成一个长字符串然后一次插入,效果会更好。
6. 源码使用与二次开发建议
这套源码的定位不是"只能按我给的流程跑",而是给你做二次开发的地基。我建议你拿到源码后,按以下顺序去熟悉它:
先打开DocXSimpleDemo的控制台工程,在 Main 方法里逐行打断点,单步执行,观察每个方法返回的对象是什么类型、有哪些属性和方法。对 DocX 的 API 体系建立直观认识,这一步大概需要半小时。
然后打开DocXTemplateDemo工程,重点研究ReplaceText和表格填充的部分。你需要真正理解模板文件里占位符写在哪里、表格结构是怎么定义的,批量生成报告的场景基本只依赖这套逻辑。
最后建议你自己动手写一个小工具,不用太复杂,做一个简单的中文简历生成器就好。输入姓名、工作经历、教育背景,然后用代码生成一个格式还挺好看的 docx 简历。做完这个项目,DocX 的核心功能你就掌握得七七八八了。
关于后续扩展方向,我补充几点:
你可以把 DocX 和 LPR(标签打印机)或者 PDF 转换器组合使用。DocX 负责内容生成,之后通过LibreOffice转换成 PDF,就能得到一套"订单确认单生成 + 邮件附件发送"的完整自动化流程。这在电商后台上经常能派上用场。
你还可以考虑做一个简单的 Web API 服务:前端上传模板 docx,后端接收 JSON 数据,动态生成合同文件返回给前端下载。部署到服务器时,只需要 .NET 运行时,不依赖 Office,这也是 DocX 在生产环境中最大的价值点。
我在实际做过的项目里,有用 DocX 生成过几千份带防伪标记的电子证书,也用它在内网工具里批量输出过周报,稳定性是经过验证的。相比 Interop 那套动不动就弹窗、死进程的老框架,DocX 的这种纯托管方案才更像是现代 C# 开发该有的样子。
最后再分享一个小技巧:如果你准备把 DocX 用到商业项目里,建议立刻去 Xceed 官网确认一下当时的授权条款。开源版本免费,但不同时期的授权范围有细微调整。提前确认好授权边界,能避免后续产品上线时遇到合规问题。这套源码我自己测下来,稳定性没问题,剩下的就看你具体业务场景了。
本文还有配套的精品资源,点击获取