C#开发WinForm比对两Excel差异时无法读取文件数据问题求助
C# WinForm Excel差异比对程序 读取与功能实现方案
一、Excel无法打开/读取的核心解决方式
首先放弃使用Microsoft.Office.Interop.Excel组件做读取,这个组件强依赖本地安装的Microsoft Office,存在32/64位版本不匹配、进程残留锁文件、权限不足等大量不可控问题,是绝大多数读取失败的根源。
直接选用无Office依赖的开源组件即可:
- 仅处理xlsx格式可选
EPPlus 4.5.3.3(MIT协议,无版权限制) - 需要兼容xls/xlsx/xlsm全格式选
NPOI,完全开源无环境依赖,直接通过Nuget安装即可使用。
二、文件读取正确实现
WinForm端先配置两个OpenFileDialog控件做文件选择,过滤规则设置为Excel文件|*.xls;*.xlsx;*.xlsm,不要写死文件路径。
读取文件时用共享读模式打开文件流,避免文件被其他进程占用时读取失败,参考实现代码:
using NPOI.SS.UserModel; using NPOI.HSSF.UserModel; using NPOI.XSSF.UserModel; using System.IO; /// <summary> /// 打开Excel文件,返回工作簿对象 /// </summary> /// <param name="filePath">Excel文件绝对路径</param> /// <returns>NPOI工作簿实例</returns> /// <exception cref="FileNotFoundException"></exception> /// <exception cref="NotSupportedException"></exception> public IWorkbook LoadExcelWorkbook(string filePath) { if (!File.Exists(filePath)) throw new FileNotFoundException("目标文件不存在", filePath); // 共享读写权限打开,避免文件被WPS/Office占用时抛出占用异常 using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { string fileExt = Path.GetExtension(filePath).ToLower(); return fileExt switch { ".xls" => new HSSFWorkbook(fs), ".xlsx" or ".xlsm" => new XSSFWorkbook(fs), _ => throw new NotSupportedException("仅支持xls/xlsx/xlsm格式的Excel文件") }; } }
三、按列名匹配的比对逻辑实现
不需要固定两个表的列数、列顺序一致,先提取每个工作表的列名和列索引的映射关系,再取列名交集作为待比对列即可:
/// <summary> /// 提取工作表的列名-列索引映射,默认第一行为列名行 /// </summary> public Dictionary<string, int> BuildColumnMap(ISheet sheet) { Dictionary<string, int> colMap = new Dictionary<string, int>(); IRow headerRow = sheet.GetRow(0); if (headerRow == null) return colMap; for (int colIndex = 0; colIndex <= headerRow.LastCellNum; colIndex++) { string colName = headerRow.GetCell(colIndex)?.ToString()?.Trim(); if (!string.IsNullOrWhiteSpace(colName) && !colMap.ContainsKey(colName)) { colMap.Add(colName, colIndex); } } return colMap; }
比对时按以下规则处理:
- 先统计两个工作表的总行数,标记仅在单表存在的行(新增/缺失行)
- 对两个表都存在的行,遍历列名交集的列,逐格转成字符串后比对值,注意空单元格、数字/文本格式差异带来的误判
- 所有差异记录字段包含:差异类型(行缺失/行新增/单元格值不匹配)、行号、列名、源表值、目标表值
四、差异结果导出
同样使用NPOI生成新的Excel文件存储结果,建议分三个工作表存储:
- 值不一致明细
- 源表存在、目标表缺失的行
- 目标表存在、源表缺失的行
导出完成后主动释放工作簿和文件流资源,避免生成的文件损坏无法打开。
五、常见读取故障排查
- 报文件被占用:检查文件流是否配置了
FileShare.ReadWrite,关闭打开该文件的WPS/Excel进程后重试 - 读取单元格内容为空:不要直接取
StringCellValue属性,用cell.ToString()读取,可自动识别公式、数字、日期等格式的内容 - 报文件格式损坏:检查文件是否是改后缀的csv/其他格式文件,这类文件需要单独适配读取逻辑
- 报COM/类未注册错误:卸载项目里引用的Interop相关组件,换成NPOI即可解决
- 平台兼容性报错:进入项目属性-生成页面,将目标平台设置为
Any CPU,取消勾选“首选32位”
内容的提问来源于stack exchange,提问作者muveszur
相关产品推荐
相关产品推荐

