简介这是一份面向 .NET 开发者的 C# DocX 源码与实操示例集合专注于在脱离 Microsoft Office 环境的情况下创建、编辑 Word 文档并支持转换为 PDF。压缩包内除 Xceed.Document.NET.dll 和 Xceed.Words.NET.dll 两个核心类库外还提供完整工程源码和 demo 示例覆盖段落、页眉页脚、图片、表格、模板生成、内容替换、自动调整表格尺寸等常见操作适合需要自动化生成报告、在线编辑文档或批量导出数据的开发场景。经由上传者实测可用注释与示例工程能帮助中初级开发者快速掌握 DocX 的 API 用法和集成方式可直接应用到成绩报告、合同文档等实际项目中。资源共 244 个文件以 cs 源码、docx 文档、dll 库文件为主穿插 png/jpg 示意图、配置文件、解决方案与说明文本整体约 4.93MB结构清晰便于按模块查阅。目前已有 272 人学习浏览是服务端或客户端程序化处理 Word/PDF 的一份实用参考资料。 干过几年C#开发的朋友一定被“生成Word文档”这个需求缠过。以前我在一个信息化项目里每周要自动把几十份业务报表导出成Word发给客户用的还是老掉牙的COM自动化结果服务器上Office组件频繁报权限异常并发一高直接内存爆炸线上问题跟进到怀疑人生。那会儿正好在GitHub上翻到DocX这个库也就是标题里说的Xceed.Words.NET——配合Xceed.Document.NET.dll源码和Demo我都亲自跑通了资料整理得也比较完整从那时起Word生成这块就再没让我头疼过。今天不聊宣传话术直接把我从环境搭建、核心API到踩坑经验全部分享出来给准备接手同类需求的人一份可以直接抄的作业。1. 为什么是DocX绕开COM自动化那套折磨1.1 三种主流方案的血泪对比做.NET技术选型时处理Word文档常见无非三条路COM Interop、Open XML SDK、DocX。先说COM Interop。它最大的问题不是功能不行而是环境依赖太重。服务端要装OfficeIIS或Windows服务里还要配DCOM权限生成文档时进程启动和回收都不可控更麻烦的是并发场景Word COM组件在Windows Server上跑并发很容易出现“RPC服务器不可用”之类的玄学错误。我身边不少老同事一听到COM直接摇头不是没有道理的。Open XML SDK是微软官方方案功能无可挑剔性能也够好但它把半个Word文档模型都暴露出来了。简单说你要给一个段落加粗得创建Run、设置RunFontProperties、处理XML属性来回十几个对象操作代码量翻倍而且学习曲线陡。如果只是生成一个中等复杂度的商务文档用SDK写起来非常痛苦。DocX现在叫Xceed.Words.NET走的是中间路线。它底层确实基于Open XML但封装了段落、表格、图片、书签、页眉页脚这些高层对象写起来就像操作普通对象模型。我用同样的功能对比过Open XML SDK写一个带三段文字和一张图片的文档可能要80行代码DocX大概25行搞定。维护成本差别非常大。1.2 DocX的定位与能力边界DocX这个项目最早是开源社区维护的库后来收编进来变成商业授权组件所以出现了两个命名空间Xceed.Words.NET和Xceed.Document.NET。前者是核心API入口DocX类就在这个空间后者放的是Document、Paragraph、Table这些底层数据模型。这是历史演进留下的痕迹不影响正常使用。它真正解决的问题是在不安装Microsoft Office的服务器上创建、编辑、保存.docx格式文档。这对后台定时任务、WebAPI导出、批量生成合同/报告这类场景是刚需。能力范围包括段落和标题排版、字体颜色尺寸设置、表格创建与合并、图片插入、书签、超链接、页眉页脚、自动页码以及模板字段替换。带宏的.doc格式不支持但docx本来就主流且没有宏问题所以不用太担心。把能力边界搞清楚后面规划功能才不会有落差。2. 环境准备两个DLL之间那点事2.1 NuGet安装还是手动引用我的建议正常开发环境直接在NuGet搜索“DocX”安装Xceed出的那个官方包就可以命令一条Install-Package DocX安装完成后项目引用里会出现两个程序集Xceed.Document.NET.dll和Xceed.Words.NET.dll。有人会疑惑是不是两个都要手动引用其实你只需要在代码里引入Xceed.Words.NET命名空间核心DocX类就在这另一个是底层依赖由包自动带上。如果哪天你从某个源码包里拿到这两个DLL文件想手动添加到老项目里那就把两个都加进来并且Xceed.Document.NET.dll的Copy Local一定要设置为True否则运行时准会报找不到程序集。离线环境没NuGet手动引用DLL是唯一办法所以源码包里同时带着这两个文件是很实用的。2.2 .NET版本兼容与包版本选择DocX最新几个大版本对目标框架有要求通常支持.NET Framework 4.6.2及以上也兼容.NET Core 3.1、.NET 5/6/7/8这些现代运行时。如果你还守着一个.NET Framework 4.0的老WinForm项目直接升级项目框架可能风险大更推荐锁定旧版DocX包比如1.x分支那个年代的包没有license限制API也简单。我日常用的时候会做一个双版本策略有预算或给客户交付的正式项目用NuGet最新稳定版加上License自己写工具脚本、临时爬数据生成文档这种内部用途直接引用老版本DLL简单粗暴没有水印和限制。这个策略看起来不够“正规”但胜在灵活尤其是个人开发者做小项目别上纲上线。3. 核心实操从一个能打开的Word文档开始3.1 创建文档、写标题、保存先来一个最小可运行示例这段代码就是标题里Demo项目的基本骨架using Xceed.Words.NET; using Xceed.Document.NET; string filePath D:\Reports\QuarterlyReport.docx; using (DocX document DocX.Create(filePath)) { document.InsertParagraph(2024年客户季度报告) .FontSize(22) .Bold() .Alignment Alignment.center; document.InsertParagraph(生成日期 DateTime.Now.ToString(yyyy-MM-dd)) .FontSize(12) .Color(Color.Gray); document.Save(); }DocX.Create是入口方法它会创建或者打开一个docx文档实例然后你用InsertParagraph在文档末尾追加段落。这里必须强调DocX实现了IDisposable一定用using包起来否则底层FileStream不会释放后面要删除或覆盖同路径文件时就会出现文件占用问题。Alignment对应的是Word里的对齐方式left、center、right枚举名很直观。Salvage方法最后会调用一次把内存里的模型落盘到磁盘。3.2 标题层级别急着踩Style的坑写复杂Word文档标题层级是刚需。DocX里最直接的想法是调用Style方法。官方Demo里也确实有这种写法var p1 document.InsertParagraph(第一章 项目背景); p1.Style(Heading1); var p2 document.InsertParagraph(第二章 数据总览); p2.Style(Heading2);看着很美但这里有个坑。DocX新建的默认文档模型里不一定预置了“Heading1”这个样式尤其是直接DocX.Create出来的空白文档很可能抛ArgumentNullException或者找不到样式。我的做法是如果文档是基于模板打开的模板里已经定义了标题样式那可以放心用Style如果是从零新建就老实手动设置字体大小和加粗效果完全可控制。3.3 段落文本的复杂格式日常业务文档一个段落里经常出现“内容重点标红超链接”这种混合排版。DocX支持在一个Paragraph里追加多个带不同格式的文本片段对应Word里的Run。比如var p document.InsertParagraph(); p.Append(恭喜客户成功完成) .FontSize(12); p.Append(《合同签署》) .Bold() .FontSize(14) .Color(Color.Red); p.Append(请查收附件。) .FontSize(12);Append之后返回的是Text对象你可以一直链式调用。这里设计思路是一个Paragraph里的一组Run共享段落对齐方式但可以有不同的字体和颜色。如果你需要某些文字是超链接则用AddHyperlink然后AppendHyperlink。3.4 用ReplaceText做模板化批量生成这是DocX在批量场景下最有价值的一招。我的做法很简单先在Word里手工做一个模板留好占位符比如尊敬的{客户名称} 您在我司的订单编号为{订单编号}预计发货日期为{发货日期}。然后在C#代码里批量替换document.ReplaceText({客户名称}, customer.Name); document.ReplaceText({订单编号}, order.Id); document.ReplaceText({发货日期}, order.ShipDate.ToString(yyyy-MM-dd));ReplaceText支持全局替换扫一遍整个文档包括表格里的文字效率很高。我做批量合同时上千份文件也就几十秒跑完这个思路比逐段InsertParagraph要快至少十倍强烈建议有类似需求的朋友用模板占位符模式。4. 进阶能力表格、图片、页眉页脚、书签4.1 表格创建、合并单元格、应用样式表格是商务文档里的重头戏。DocX创建表格的API很友好var table document.AddTable(3, 4); for (int row 0; row 3; row) { for (int col 0; col 4; col) { table.Rows[row].Cells[col].Paragraphs[0] .Append($第{row}行第{col}列); } } // 合并第一行的前两个单元格 table.Rows[0].MergeCells(0, 1); // 设置表格整体样式 table.Design TableDesign.LightShadingAccent1; document.InsertTable(table);这里要解释几个容易忽略的点。AddTable创建的是不包含在文档正文里的虚拟表格你必须调用InsertTable才能真正插入文档。每个单元格默认自带一个Paragraph直接Append文本就好。MergeCells合并的是横向连续区域纵向合并要自己循环处理单元格内容并隐藏被合并的单元格稍微麻烦一点。Design枚举只是DocX预置的一套格式实际是否生效取决于docx模板里有没有对应样式定义没有就只保留边框和基础布局。4.2 图片别用控件里的居中方式直接套插入图片的场景很常见签名、Logo、产品图。基本代码长这样using (var fs File.OpenRead(D:\Images\company_logo.png)) { Image img document.AddImage(fs); Picture pic img.CreatePicture(100, 40); var p document.InsertParagraph(); p.AppendPicture(pic); p.Alignment Alignment.center; }CreatePicture的两个参数是宽度和高度单位是像素。注意图片居中不是靠Picture的某个属性而是给它所在的Paragraph设置Alignment这个和Word处理图片的底层逻辑一致理解了就不会在这卡壳。加多张图片时需要控制间距用段落SpacingAfter属性设置。4.3 页眉页脚和自动页码正式的商务文档页眉页脚总得有点公司名字和页码。DocX用法如下document.AddHeaders(); Header header document.Headers.Odd; header.InsertParagraph(某某科技有限公司内部资料) .Alignment Alignment.center; document.AddFooters(); Footer footer document.Footers.Odd; footer.InsertParagraph(第 ) .AppendPageNumber(PageNumberFormat.normal) .Append( 页 / 共 ) .AppendPageCount(PageNumberFormat.normal) .Append( 页);AddHeaders和AddFooters是必须的它们会初始化默认页眉页脚区域。AppendPageNumber和AppendPageCount是DocX自带的方法文档生成后页码会自动计算不需要手动画域代码。头几次用的时候我一度担心页眉页脚会不会覆盖正文实际上它处理得很干净放心用。4.4 书签与超链接书签和超链接适合生成电子版操作手册、目录跳转这类文档。Type代码示例// 添加书签先创建一个Bookmark对象通过add书签插入指定段落 var bookmark document.AddBookmark(章节一跳转, 这是章节一跳转到的内容); // 把书签关联到某个段落上 var p document.InsertParagraph(第一章 概述); p.AppendBookmark(bookmark); // 超链接 var hyperlink document.AddHyperlink(点击访问官网, new Uri(https://example.com)); var lp document.InsertParagraph(); lp.AppendHyperlink(hyperlink);书签API在使用时建议查阅一下当前包版本的方法签名不同版本略有差异但大方向一致先AddBookmark再AppendBookmark到段落。超链接一般变化不大照着写就能跑通。5. 亲测中踩过的最头疼的几个问题5.1 中文字体经常“时灵时不灵”这是最多人遇到的问题。代码里明明设置了FontSize、Bold中文也能显示但用宋体、微软雅黑时总是变成默认主题字体。原因在于docx里中文文本使用的是东亚字体属性East AsianDocX的Font方法默认设置的可能是asii字体中文不在默认字体作用范围内结果Word渲染时用了主题字体。我自己验证过两个有效的解决办法。最直接的是在生成完后给涉及中文的每个段落都调用 Font(宋体) 或 Font(微软雅黑)个别情况还要同时给文本的ComplexScript属性做设置保证中英混排时一致性。另一个思路是修改文档的Normal样式把默认字体统一成中文字体这样大部分段落就不用每个单独设置了。我实际项目里是这两种方案结合虽然看起来粗暴但最终生成的文档在Word/WPS里都显示正常再也没被字体问题投诉过。5.2 评估版水印与版本策略怎么权衡DocX被收编后NuGet上的最新版进入商业授权模式没注册License时有时会出现水印、限制或提示具体表现为导出文档中夹带评估标记某些高级功能直接抛异常。这在交付客户的项目里是不可接受的。我的处理方式分两种情况。一个简短例子在应用启动入口处执行Xceed.Licenser.LicenseKey 你的授权密钥;正规商用就买授权在入口注册一次。如果只是自己内部用、学习、写工具直接用老版本1.x的DLL即可那个版本完全免费生成文档无任何限制。网上很多“源码demo”里的两个DLL其实就是老版本亲测能正常跑。版本选择没有银弹关键是搞清楚你的使用场景是否涉及对外商业发布。5.3 DLL引用冲突和运行时“找不到程序集”一个真实项目里如果同时引用了Xceed其他产品比如Xceed DataGrid、Xceed Toolkit很容易出现两个程序集版本不一致运行时抛FileLoadException提示找不到特定版本的Xceed.Document.NET。看到的报错信息往往很长但核心就是版本号不匹配。排查顺序先看项目里所有Xceed相关包版本是否一致不一致时统一到同一个版本如果手上有多个DLL确认输出目录里是同一套版本不要一个release一个debug混着放。引用的DLL属性里Copy Local一定要True否则发布时文件不带上客户机器上必定报错。这里必须多说一句遇到这种问题先别改代码八成是包的引用配置问题。5.4 句柄泄漏、文件占用和并发问题DocX实例不释放生成的文件就会被占用后续任何Delete、Move都会失败。这个在前面提过但还是要单独强调多线程批量生成时每个线程创建自己的DocX实例绝不能共享同一个实例每个实例必须using或try-finally释放。批量循环几百次时如果不释放句柄最后可能磁盘上什么文件都没生成只剩一堆被锁住的句柄。更隐蔽的是Save()之后还要注意并非所有文件流都能在Save里关闭。稳妥的做法是Save()后不要依赖自动释放把整个操作包在using中。我的习惯写法using (var doc DocX.Create(path)) { // ... 操作 doc.Save(); } // 到这里肯定释放5.5 DocX在服务器上反而更稳定最后给个定心丸。过去COM方案在服务器上总有这那的神秘问题DocX因为是托管程序集只要服务器装了对应版本的.NET运行时就能跑完全不需要Office。我在好几台Windows Server上放过定时任务生成几千份docx从未崩过。唯一的注意点是配置好写入目录的权限别让进程没权限创建文件。这个库在服务端环境下的稳定性是我一直敢在项目里大面积使用它的根本原因。最后再分享一个小技巧生成大量重复结构文档时不要用代码从头画表格和段落先在Word里做一份漂亮模板用占位符标出需要修改的位置代码里只做ReplaceText和局部段落追加。这套模式能极大减少排版工作量也让最终文档永远保持模板的专业感。DocX这套源码和Demo在我团队里用了一年多从几十页的合同到带目录的管理手册都扛得住值得放进你的工具箱。本文还有配套的精品资源点击获取