优先选用EPPlus而非Microsoft.Office.Interop.Excel,因其纯托管、不依赖Office、支持.NET Core/5+、性能好;Interop需本机安装Office、易致进程残留、STA限制多、服务器部署不可行。

直接用 Microsoft.Office.Interop.Excel 写 Excel 文件,在生产环境里基本等于给自己埋雷——需要本机装 Office、进程残留、线程套间(STA)限制、性能差、服务器部署几乎不可行。真要写入 Excel,优先选 EPPlus(.NET 5+ 推荐 ExcelPackage,即 EPPlus 6+ 的正式命名)。
为什么不用 Interop,而选 EPPlus
Interop 调用的是 Excel 桌面程序 COM 接口,不是“生成文件”,而是“启动 Excel 进程写数据”。这意味着:
- 服务器没装 Office 就直接抛
COMException,错误信息常是Retrieving the COM class factory for component with CLSID... - 每次写完不显式调用
Quit()+ 强制 GC,Excel 进程会卡在后台,积压后系统假死 - 多线程并发写时,必须把整个调用链塞进 STA 线程,
Thread.SetApartmentState(ApartmentState.STA)很容易漏或配错 - 生成 .xlsx 文件体积大、打开慢,因为实际是操作内存中一个“活”的 Excel 实例
EPPlus 是纯托管库,只读写 OOXML 格式(即 .xlsx),不依赖 Office,支持 .NET Core / .NET 5+,API 直观,性能好得多。
EPPlus 6+(ExcelPackage)基础写入示例
EPPlus 5.x 开始商用需授权,6.x 起回归 MIT 开源协议(但仅限非商业用途;商业项目请确认最新许可条款)。安装包为 EPPlus,主命名空间是 OfficeOpenXml。
关键步骤:
- 调用
ExcelPackage.LicenseContext = LicenseContext.NonCommercial(开发/学习可设为NonCommercial;生产商用务必查官网许可) - 用
new ExcelPackage(new FileInfo(path))创建包,或用new ExcelPackage()纯内存操作 -
package.Workbook.Worksheets.Add("Sheet1")获取工作表,再用worksheet.Cells[row, col].Value = ...赋值 - 最后
package.Save()(文件路径方式)或package.Stream(流方式返回给 Web 响应)
简单写入代码片段:
using OfficeOpenXml;
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Data");
worksheet.Cells[1, 1].Value = "姓名";
worksheet.Cells[1, 2].Value = "年龄";
worksheet.Cells[2, 1].Value = "张三";
worksheet.Cells[2, 2].Value = "28";
package.SaveAs(new FileInfo(@"C:\output.xlsx"));
常见写入失败原因与绕过方法
EPPlus 报错大多集中在初始化和单元格操作阶段:
-
System.IO.FileLoadException: Could not load file or assembly 'System.Drawing.Common':.NET 6+ 默认不包含该组件,需手动安装System.Drawing.CommonNuGet 包 -
NullReferenceException在worksheet.Cells[...]:未检查worksheet是否为 null(Add()返回值可能为空,尤其名字重复时) - 中文乱码或格式错乱:EPPlus 默认使用 UTF-8,只要文件保存路径不含非法字符、不涉及特殊字体设置,一般不会乱码;若导出到 Web,注意响应头设
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet和Content-Disposition - 大数据量卡顿(如写 10 万行):避免逐单元格赋值,改用二维数组 +
worksheet.Cells["A1"].LoadFromCollection(...)批量导入,性能提升 10 倍以上
Web API 中安全返回 Excel 文件(ASP.NET Core)
别用 SaveAs() 写磁盘,直接走流。关键是释放资源、设对 MIME 类型、防止文件名含恶意字符:
- 用
MemoryStream构造ExcelPackage,写完调package.Stream.Position = 0 - 文件名用
Uri.EscapeDataString("报表.xlsx")编码,避免 IE 下乱码 - 返回
File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName) - 务必在
using块内完成所有操作,避免 Stream 被提前释放
这个环节最容易漏掉 Position = 0,导致下载空文件却无报错。
EPPlus 的坑不在语法,而在初始化上下文和资源生命周期。写完记得检查 ExcelPackage 是否被正确 dispose,流是否重置位置,以及许可证模式是否匹配实际用途——这三个点,90% 的“写不进去”问题都出在这儿。


















