WPF中用NPOI导入Excel至DataTable时前两列数据缺失问题
问题解决:NPOI导入Excel前两列缺失及空行问题
核心问题分析
- 前两列数据缺失:你的代码遍历表头和读取数据时,依赖
foreach (var cell in headerRow)和row.GetCell(j),但NPOI默认仅读取实际被创建的单元格(比如Excel中部分单元格可能因编辑方式导致底层未被标记为存在),同时直接使用cell.ToString()在部分单元格类型下可能返回空值。 - 空行问题:
sheet.LastRowNum会包含Excel中所有被编辑过的行(包括曾经输入内容后清空的行),直接遍历会将空行同步到DataTable中。
修改后的完整代码
private void CreateDataTable() { String filePath = @"filepath"; using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { var workbook = WorkbookFactory.Create(fileStream); var sheet = workbook.GetSheetAt(0); var dt = new DataTable(); var headerRow = sheet.GetRow(0); dt.Columns.Clear(); dt.Rows.Clear(); // 按表头行总列数创建列,确保所有列都被覆盖 for (int j = 0; j < headerRow.LastCellNum; j++) { // 强制获取单元格,不存在则视为空白 var cell = headerRow.GetCell(j, MissingCellPolicy.CREATE_NULL_AS_BLANK); dt.Columns.Add(cell.ToString(), typeof(string)); } // 从第2行开始读取数据 for (int i = 1; i <= sheet.LastRowNum; i++) { var row = sheet.GetRow(i); // 跳过空行 if (row == null || IsRowEmpty(row)) continue; var dataRow = dt.NewRow(); for (int j = 0; j < dt.Columns.Count; j++) { var cell = row.GetCell(j, MissingCellPolicy.CREATE_NULL_AS_BLANK); // 安全获取单元格值,适配不同类型 dataRow[j] = GetCellValue(cell); } dt.Rows.Add(dataRow); } // 绑定到DataGrid DataGrid.ItemsSource = dt.DefaultView; } } // 判断行是否为空行 private bool IsRowEmpty(IRow row) { for (int j = 0; j < row.LastCellNum; j++) { var cell = row.GetCell(j, MissingCellPolicy.CREATE_NULL_AS_BLANK); if (!string.IsNullOrEmpty(GetCellValue(cell))) return false; } return true; } // 安全获取单元格值,适配Excel各种数据类型 private string GetCellValue(ICell cell) { if (cell == null) return string.Empty; return cell.CellType switch { CellType.String => cell.StringCellValue, CellType.Numeric => DateUtil.IsCellDateFormatted(cell) ? cell.DateCellValue.ToString() : cell.NumericCellValue.ToString(), CellType.Boolean => cell.BooleanCellValue.ToString(), CellType.Formula => cell.CachedFormulaResultType switch { CellType.String => cell.StringCellValue, CellType.Numeric => cell.NumericCellValue.ToString(), _ => string.Empty }, _ => string.Empty }; }
关键修改点说明
- 表头列创建:改用
headerRow.LastCellNum循环所有列索引,配合MissingCellPolicy.CREATE_NULL_AS_BLANK强制获取每个单元格,避免遗漏列。 - 单元格值读取:新增
GetCellValue方法,根据单元格类型安全获取值,替代直接ToString(),避免类型转换导致的空值。 - 空行过滤:新增
IsRowEmpty方法判断空行,遍历行内所有单元格,确认无有效内容后跳过该行。
内容的提问来源于stack exchange,提问作者Jeslyn
相关产品推荐
相关产品推荐

