最稳方案是用 epplus 5.8.7(免费稳定版),禁用 interop;导出用 loadfromdatatable(dt, true),导入用 cells[2,1,...].todatatable();.xls 改用 npoi;中文、公式、日期需显式处理。
用 epplus 读写 excel(.xlsx)最稳
直接说结论:别碰 microsoft.office.interop.excel,它依赖 office 安装、线程不安全、服务器上基本跑不起来;epplus 是目前 c# 生态里对 .xlsx 支持最成熟、文档最清晰、性能也够用的开源库。
常见错误现象:EPPlus 6.x 起强制要求商业许可(免费版有水印+限制),但 5.8.7 是最后一个完全免费且稳定的版本,别盲目升级到 6.x。
实操建议:
- 用 NuGet 安装
EPPlus5.8.7:Install-Package EPPlus -Version 5.8.7 - 代码开头必须加
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;(哪怕你商用,先跑通再合规) - 读取时别用
Load()直接传Stream,要确保流未被关闭、可重读;推荐用new FileInfo(path)构造 - 写入后记得调用
package.Save();,否则文件为空
DataTable 和 Excel 互转最常用场景
多数业务需求就是把数据库查出的 DataTable 导出成 Excel,或把用户上传的 Excel 解析回 DataTable ——EPPlus 原生支持,但默认行为容易踩坑。
使用场景:后台导出报表、批量导入配置、Excel 数据清洗
实操建议:
- 导出:
worksheet.Cells["A1"].LoadFromDataTable(dt, true);第二个参数true表示首行写列名,别漏掉 - 导入:用
worksheet.Cells[2, 1, lastRow, lastCol].ToDataTable(),注意起始行是 2(跳过标题行),别用1,1否则会把列名当数据读 - 如果
DataTable有空列或类型混乱,EPPlus推断类型可能出错,建议提前用dt.Columns[i].DataType = typeof(string);固定列类型
处理 .xls(旧格式)只能换库
EPPlus 完全不支持 .xls(Excel 97–2003),强行打开会抛 System.IO.InvalidDataException: Invalid signature。
实操建议:
- 优先让前端/用户改用 .xlsx 格式上传,比换库简单得多
- 真要兼容 .xls,用
NPOI(注意不是POI):Install-Package NPOI -
NPOI里HSSFWorkbook处理 .xls,XSSFWorkbook处理 .xlsx,别混用;读取时需判断扩展名再选类 -
NPOI的 API 比EPPlus更底层,比如设单元格值必须显式调用cell.SetCellValue("xxx"),不能直接赋值
中文乱码、公式不计算、日期变数字
这些不是 bug,是 Excel 文件结构和 .NET 类型映射的固有表现,不处理就会在生产环境突然暴露。
实操建议:
- 中文乱码:确保保存时用
Encoding.UTF8(仅影响文本流,EPPlus写文件本身无此问题;但如果你用File.WriteAllText写 CSV 再转 Excel 就得注意) - 公式不生效:写入公式后必须调用
cell.Calculate()或worksheet.Calculate(),否则 Excel 打开显示为 0 或原始公式字符串 - 日期变数字:Excel 里日期本质是浮点数,
EPPlus默认按OleVariant解析;读取时用cell.GetValue<datetime>()</datetime>,别用cell.Value.ToString()
真正麻烦的是跨平台部署时的字体渲染和公式引擎差异,比如 Linux 服务器没安装中文字体,导出的 Excel 中文可能显示方框——这事没法靠代码绕过,得配环境。











