using NPOI.SS.UserModel; using System; using System.Data; using System.IO; namespace YiDa_WinForm.Utils { /// /// Excel 解析工具类 /// public static class ExcelHelper { /// /// 解析Excel为DataTable /// public static DataTable GetExcel(string filePath) { IWorkbook iwkX = null; DataTable dt = new DataTable(); try { // 使用 using 包裹 FileStream,确保资源快速释放,且减少文件占用 using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, FileOptions.SequentialScan)) { iwkX = WorkbookFactory.Create(fs); } if (iwkX == null || iwkX.NumberOfSheets == 0) { LogHelper.AppendLog("Excel文件中无Sheet,解析为空"); return dt; } ISheet sheet = iwkX.GetSheetAt(0); if (sheet.LastRowNum < 1) // 无数据行(仅表头) { LogHelper.AppendLog("Excel文件中无有效数据行"); return dt; } // 读取表头(减少重复判断) IRow headerRow = sheet.GetRow(0); for (int i = 0; i < headerRow.LastCellNum; i++) { ICell cell = headerRow.GetCell(i); string columnName = cell == null ? $"未知列_{i}" : cell.ToString().Trim(); if (dt.Columns.Contains(columnName)) { columnName += $"_{i}"; } dt.Columns.Add(columnName); } // 批量读取数据行,减少空行判断的冗余操作 int startRow = 1; // 跳过表头 for (int i = startRow; i <= sheet.LastRowNum; i++) { IRow dataRow = sheet.GetRow(i); if (dataRow == null) continue; DataRow dr = dt.NewRow(); bool isEmptyRow = true; // 空行标记 for (int j = 0; j < dt.Columns.Count; j++) { ICell cell = dataRow.GetCell(j, MissingCellPolicy.CREATE_NULL_AS_BLANK); string cellValue = cell.ToString().Trim(); dr[j] = cellValue; // 优化4:只要有一个单元格非空,就不是空行(减少后续 All 遍历) if (!string.IsNullOrEmpty(cellValue)) { isEmptyRow = false; } } if (!isEmptyRow) { dt.Rows.Add(dr); } } LogHelper.AppendLog($"Excel解析成功:{dt.Rows.Count}行数据,{dt.Columns.Count}列"); } catch (Exception ex) { LogHelper.AppendLog($"Excel解析失败:{ex.Message}"); } finally { iwkX?.Close(); } return dt; } } }