C#读取Excel文件内容 C#如何解析.xlsx文件数据

来源:这里教程网 时间:2026-02-21 17:41:24 作者:

EPPlus
读取
.xlsx
是目前最稳的选择

直接说结论:别用

Microsoft.Office.Interop.Excel
,它依赖 Office 安装、线程不安全、服务器上基本跑不起来;也别碰已停更的
NPOI
旧版(0.9x),对 .xlsx 支持弱且容易抛
Invalid header signature
。推荐用现代、纯托管、NuGet 开箱即用的
EPPlus
(v6+,注意需 .NET 5+ 或 .NET Framework 4.6.1+)。

安装命令:

dotnet add package EPPlus
(若用 .NET Core/.NET 5+)或通过 NuGet 包管理器安装
EPPlus
v6.x。

关键点:

EPPlus
不需要 Excel 软件,也不调 COM,纯内存解析,适合后台服务
v6+ 默认启用「商业用途需授权」提示,若仅内网/非分发场景,可加一行代码关闭:
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
读取时默认不加载样式、公式结果(只读值),性能好;如需公式求值,得手动调用
worksheet.Calculate()

读取第一个 Sheet 的数据:跳过空行、处理标题行

常见需求是把 Excel 表格当二维数据源用,比如首行为列名,后面为记录。用

EPPlus
可这样写:

using (var package = new ExcelPackage(new FileInfo("data.xlsx")))
{
    var worksheet = package.Workbook.Worksheets[0]; // 第一个 sheet
    var rowCount = worksheet.Dimension?.Rows ?? 0;
    var colCount = worksheet.Dimension?.Columns ?? 0;
<pre class='brush:php;toolbar:false;'>var data = new List<Dictionary<string, object>>();
if (rowCount < 2) return data;
// 假设第1行是 header
var headers = Enumerable.Range(1, colCount)
    .Select(c => worksheet.Cells[1, c].Text.Trim())
    .ToArray();
for (int row = 2; row <= rowCount; row++)
{
    var values = new Dictionary<string, object>();
    bool allEmpty = true;
    for (int col = 1; col <= colCount; col++)
    {
        var cell = worksheet.Cells[row, col];
        var val = cell.Text; // 用 .Text 更安全(避免 null 引用),.Value 是 object 类型需判空转型
        values[headers[col - 1]] = val;
        if (!string.IsNullOrWhiteSpace(val)) allEmpty = false;
    }
    if (!allEmpty) data.Add(values);
}

}

注意:

worksheet.Dimension
可能为
null
(空表),务必判空
别直接用
cell.Value
——它可能是
double
DateTime
null
,类型不统一;
cell.Text
总是字符串,语义更接近「用户看到的内容」
Excel 行号/列号从 1 开始,不是 0,
Cells[row, col]
别写反

遇到
System.IO.FileFormatException: File contains corrupted data

这通常不是文件真坏了,而是你用了错误的库或打开方式:

FileStream
打开后没设
FileShare.Read
,被其他进程占用 → 改用
new FileInfo(path)
构造
ExcelPackage
,它内部会正确处理流
文件其实是
.xls
(OLE 复合文档格式),但扩展名错写成
.xlsx
→ 用十六进制编辑器看前 8 字节:真正的
.xlsx
应以
50 4B 03 04
(PK..)开头;
.xls
D0 CF 11 E0
(DOCFILE)
用低版本
EPPlus
(v4/v5)打开由新版 Excel(如 Microsoft 365)保存的强加密或含新特性(如动态数组公式)的文件 → 升级到 v6.2+ 并确认
LicenseContext
设置正确

读取指定列、跳过隐藏行、识别合并单元格

业务中常要按列名取值,或过滤掉人工隐藏的行:

按列名查值:先用
headers
数组找到列索引,再取对应
cell.Text
,比硬编码列号更健壮
跳过隐藏行:
worksheet.Row(row).Hidden
返回
true
continue
合并单元格:用
worksheet.MergedCells
获取所有合并区域(如
"A1:C1"
),再用
worksheet.Cells[row, col].Merged
判断当前单元格是否属于合并区;若属合并区,只取左上角单元格的值即可,其余为空
日期列读出来是数字?那是 Excel 序列号(如 44197 = 2021-01-01),用
DateTime.FromOADate(cell.Value as double?)
转换,但前提是
cell.Value
确实是
double
;更稳妥仍是先读
cell.Text
DateTime.TryParse

合并单元格和隐藏行逻辑容易漏,尤其在报表类 Excel 中,不检查就会导致数据错位或重复。

相关推荐