C#读写Excel推荐EPPlus(.NET 5+)或NPOI(兼容.NET Framework),避免使用线程不安全、依赖Office安装的Interop;EPPlus需注意许可证、索引从1开始、空值判断;NPOI需注意流不关闭、行/单元格需手动创建;二者均不自动计算公式,文件需校验魔数防损坏。

C# 读写 Excel 文件,别用 Microsoft.Office.Interop.Excel —— 它依赖本地 Office 安装、线程不安全、服务器部署极易崩溃,且性能差。
真正可靠、轻量、跨平台的方案是 EPPlus(.NET 5+ 推荐)或 NPOI(兼容 .NET Framework)。下面按实际使用场景分点说明。
EPPlus 读取 Excel:支持 .xlsx,不依赖 Office
- EPPlus 5.x 仅支持 .NET Framework,6.x+ 要求 .NET 5 或更高版本,且默认禁用旧加密格式(如 Excel 97-2003 的 .xls)
- 读取时需注意:
ExcelPackage.LicenseContext = LicenseContext.NonCommercial(开源版仅限非商业用途),商用必须购买许可证 - 工作表索引从 1 开始,不是 0;空行/列不会自动跳过,需手动判断
是否为worksheet.Cells[row, col].Valuenull - 示例:读取第一张表的 A1 单元格
using (var package = new ExcelPackage(new FileInfo("data.xlsx")))
{
var worksheet = package.Workbook.Worksheets[1];
var value = worksheet.Cells[1, 1].Value?.ToString();
}EPPlus 写入 Excel:避免 Save() 失败的常见原因
- 目标路径的父目录必须已存在,否则
Save()抛出DirectoryNotFoundException - 若文件已打开(比如被 Excel 进程占用),会抛出
IOException,建议加FileShare.ReadWrite - 单元格赋值类型要匹配:写字符串用
.Value = "text",写日期用DateTime类型,别传字符串"2024-01-01"后指望自动识别 - 设置列宽、样式等操作必须在
Save()前完成,且不能对已释放的ExcelPackage对象操作
var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
worksheet.Cells[1, 1].Value = "Hello";
worksheet.Column(1).Width = 15;
package.SaveAs(new FileInfo("output.xlsx"));NPOI 替代方案:需要兼容 .xls 或 .NET Framework 4.8
- NPOI 支持
.xls(HSSF)和.xlsx(XSSF),但 HSSF 已停止维护,新项目一律用 XSSF - 读取
.xls时若遇到Invalid header signature,大概率是文件实际为.xlsx却用了HSSFWorkbook -
XSSFWorkbook构造函数接收Stream,但该流不能被关闭,否则后续读取报ObjectDisposedException;推荐用new MemoryStream(byteArray)并设leaveOpen: true - 创建单元格前必须先获取或创建行:
row = sheet.GetRow(0) ?? sheet.CreateRow(0); cell = row.GetCell(0) ?? row.CreateCell(0);
using (var fs = new FileStream("data.xlsx", FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous))
using (var workbook = new XSSFWorkbook(fs))
{
var sheet = workbook.GetSheetAt(0);
var cell = sheet.GetRow(0)?.GetCell(0);
var value = cell?.StringCellValue;
}EPPlus 和 NPOI 都不处理 Excel 公式计算结果(比如 =SUM(A1:A10) 只返回公式字符串,除非调用 EvaluateFormulaCell)。如果业务依赖实时计算值,要么预先把 Excel 用 Excel 打开另存为“值”,要么换用 ClosedXML(但它的公式支持也有限)。
另外,任何库都无法绕过 Excel 文件本身的损坏风险——上传文件前务必校验 ContentType 和魔数(如 .xlsx 开头应为 PK\x03\x04),否则解析时直接 InvalidDataException。










