You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:51:32