17370845950

C# 操作Excel方法 C#如何读取和写入Excel文件
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].Value 是否为 null
  • 示例:读取第一张表的 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 类型,别传字符串 "2025-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