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

C#如何在应用启动时读取Excel文件数据并显示到DataGridView

实现思路
  • 你现有代码的核心问题是获取到Excel的已用区域Range后,没有执行单元格内容读取逻辑就直接释放了COM对象,只需要在获取行列数之后、释放COM资源之前,补充表头读取、逐行数据写入DataTable的逻辑,最后将DataTable绑定到DataGridView即可。
  • 读取逻辑分两步:先读取第一行内容作为DataTable的列名(如果第一行不是表头可自行调整起始索引),再从第二行开始逐行读取单元格值存入DataTable。
  • 所有读取操作完成后再执行GC回收和COM对象释放,避免中途对象被释放导致读取失败;读取过程中需要处理单元格空值、DBNull的情况,避免抛出空引用异常。
修改后完整代码
private void OpenExcelFile()
{
    System.Data.DataTable dt = new System.Data.DataTable(); // Excel数据容器
    // 找第一个匹配名称带Contacts的Excel文件,如需读取多个可去掉FirstOrDefault逻辑
    var targetFile = Directory.GetFiles(this.ExcelFolderPath)
        .FirstOrDefault(p => p.Contains("Contacts") && (p.EndsWith(".xlsx") || p.EndsWith(".xls")));
    
    if (targetFile == null)
    {
        MessageBox.Show("未找到目标Contacts文件");
        return;
    }

    Microsoft.Office.Interop.Excel.Application excelApp = null;
    Microsoft.Office.Interop.Excel.Workbook excelWorkbook = null;
    Microsoft.Office.Interop.Excel._Worksheet excelWorksheet = null;
    Microsoft.Office.Interop.Excel.Range excelRange = null;

    try
    {
        excelApp = new Microsoft.Office.Interop.Excel.Application();
        excelApp.Visible = false; // 后台运行不显示Excel窗口
        excelWorkbook = excelApp.Workbooks.Open(targetFile);
        excelWorksheet = excelWorkbook.Sheets[1]; // 默认读第一个工作表,可按需改索引或表名
        excelRange = excelWorksheet.UsedRange;

        int rowCount = excelRange.Rows.Count;
        int colCount = excelRange.Columns.Count;

        // 1. 读取表头(第一行),生成DataTable列
        for (int col = 1; col <= colCount; col++)
        {
            string colName = (excelRange.Cells[1, col] as Microsoft.Office.Interop.Excel.Range)?.Text?.ToString();
            // 处理空列名,避免绑定报错
            if (string.IsNullOrWhiteSpace(colName))
            {
                colName = $"列{col}";
            }
            // 处理重复列名
            while (dt.Columns.Contains(colName))
            {
                colName += "_1";
            }
            dt.Columns.Add(colName);
        }

        // 2. 逐行读取数据(从第二行开始,第一行是表头)
        for (int row = 2; row <= rowCount; row++)
        {
            DataRow dataRow = dt.NewRow();
            for (int col = 1; col <= colCount; col++)
            {
                var cellValue = (excelRange.Cells[row, col] as Microsoft.Office.Interop.Excel.Range)?.Value2;
                dataRow[col - 1] = cellValue ?? DBNull.Value; // 处理空单元格
            }
            dt.Rows.Add(dataRow);
        }

        // 3. 绑定到DataGridView
        dataGridView1.AutoGenerateColumns = true; // 自动生成列,如需自定义列可设为false
        dataGridView1.DataSource = dt;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"读取Excel失败:{ex.Message}");
    }
    finally
    {
        // 统一释放COM资源,顺序从最内层到最外层,异常场景也能正常关闭Excel进程
        GC.Collect();
        GC.WaitForPendingFinalizers();
        if (excelRange != null) Marshal.ReleaseComObject(excelRange);
        if (excelWorksheet != null) Marshal.ReleaseComObject(excelWorksheet);
        if (excelWorkbook != null)
        {
            excelWorkbook.Close();
            Marshal.ReleaseComObject(excelWorkbook);
        }
        if (excelApp != null)
        {
            excelApp.Quit();
            Marshal.ReleaseComObject(excelApp);
        }
    }
}
注意事项
  • 如果你的Excel文件第一行不是表头是有效数据,只需要把列生成逻辑改为自动生成列1/列2格式的默认列名,数据读取的起始行从1开始即可。
  • 上述代码默认读取第一个名称匹配的Contacts文件,如果需要合并目录下所有匹配文件的内容,去掉FirstOrDefault判断,在循环内追加读取工作表数据到同一个DataTable即可。
  • 使用Microsoft.Office.Interop.Excel要求程序运行的设备必须安装对应版本的Microsoft Office,如果需要无Office环境运行,建议替换为NPOI、EPPlus等不依赖Office的开源类库实现读取逻辑。
  • 如果读取操作放在后台线程执行,绑定DataGridView时必须通过Invoke切换到UI线程操作,否则会抛出跨线程访问控件的异常。

内容的提问来源于stack exchange,提问作者jacko10101

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:48:21