C#开发多格式转换工具时Excel数据显示到DataGrid问题求助
问题根因
你代码的核心故障点是 XlsxReaderAndConverter 虽然继承了MainWindow,但你新创建的这个类实例和当前正在运行的主窗口不是同一个对象,它内部的dtGrid、cmbColumn控件都没有初始化,运行到控件操作的代码时会直接抛出空引用异常,导致数据无法正常显示。
同时还存在两个隐性问题:
- 拼接
|再拆分的逻辑如果遇到单元格本身包含|会出现列错位 - 没有释放Office COM对象,会导致Excel进程残留在系统后台
修复方案
步骤1:重写XlsxReaderAndConverter类,剥离UI操作
这个类只负责读取Excel返回DataTable,不要操作任何UI控件:
using System.Data; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; class XlsxReaderAndConverter { public string FileName { get; set; } public XlsxReaderAndConverter(string fileName) { FileName = fileName; } public DataTable ReadExcel() { DataTable dt = new DataTable(); Application excelApp = null; Workbook excelBook = null; Worksheet excelSheet = null; Range excelRange = null; try { excelApp = new Application(); excelBook = excelApp.Workbooks.Open(FileName, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0); excelSheet = (Worksheet)excelBook.Worksheets.Item[1]; excelRange = excelSheet.UsedRange; // 初始化列 for (int colCnt = 1; colCnt <= excelRange.Columns.Count; colCnt++) { var cellVal = (excelRange.Cells[1, colCnt] as Range)?.Value2; // 处理表头为空的情况 string columnName = cellVal?.ToString() ?? $"列{colCnt}"; dt.Columns.Add(columnName, typeof(string)); } // 读取行数据,直接赋值不需要拼接拆分 for (int rowCnt = 2; rowCnt <= excelRange.Rows.Count; rowCnt++) { DataRow dr = dt.NewRow(); for (int colCnt = 1; colCnt <= excelRange.Columns.Count; colCnt++) { var cellVal = (excelRange.Cells[rowCnt, colCnt] as Range)?.Value2; dr[colCnt - 1] = cellVal?.ToString() ?? ""; } dt.Rows.Add(dr); } return dt; } finally { // 强制释放COM对象,避免残留Excel进程 if (excelRange != null) Marshal.ReleaseComObject(excelRange); if (excelSheet != null) Marshal.ReleaseComObject(excelSheet); if (excelBook != null) { excelBook.Close(false); Marshal.ReleaseComObject(excelBook); } if (excelApp != null) { excelApp.Quit(); Marshal.ReleaseComObject(excelApp); } } } }
步骤2:修改主窗口调用逻辑
UI操作放回主窗口实例执行,避免空引用:
case ".xlsx": XlsxReaderAndConverter xlsxReaderAndConverter = new XlsxReaderAndConverter(fileName); DataTable resultDt = xlsxReaderAndConverter.ReadExcel(); // 绑定数据到当前窗口的控件 dtGrid.ItemsSource = resultDt.DefaultView; cmbColumn.Items.Clear(); for(int i=1;i<=resultDt.Columns.Count;i++) { cmbColumn.Items.Add(i); } break;
额外优化建议
如果不想依赖用户本地安装Excel,可以改用EPPlus、NPOI等开源的xlsx读取库,兼容性更好,也不需要处理复杂的COM对象释放逻辑。
内容的提问来源于stack exchange,提问作者Klaatu
相关产品推荐
相关产品推荐

