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

WPF中用NPOI导入Excel至DataTable时前两列数据缺失问题

问题解决:NPOI导入Excel前两列缺失及空行问题

核心问题分析

  1. 前两列数据缺失:你的代码遍历表头和读取数据时,依赖foreach (var cell in headerRow)和row.GetCell(j),但NPOI默认仅读取实际被创建的单元格(比如Excel中部分单元格可能因编辑方式导致底层未被标记为存在),同时直接使用cell.ToString()在部分单元格类型下可能返回空值。
  2. 空行问题: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:18:15