首页 新闻 会员 周边

C# NPOI中导入Excel表格,表头有空表格,有的Excel表格显示,有的Excel表格不显示。

0
悬赏园豆:160 [已解决问题] 解决于 2023-11-08 10:04

本人小白在进行Winform开发时,用NPOI导入Excel表格,发现表头有空单元格的表格,有时会显示Column1列和Column2列来显示。有的表格不会,直接吃掉了那一列。不知道是哪里出了问题,是表格问题吗?有人能回答感激不尽!
代码参考如下:

public void ImportExcelToDataGridView(string filePath,DataGridView dataGridView, DataTable dataTable)
        {
            
            IWorkbook workbook;
            if (Path.GetExtension(filePath)==".xls")
            {
                using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    workbook = new HSSFWorkbook(file);
                }
            }
            else if (Path.GetExtension(filePath)==".xlsx")
            {
                using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    workbook = new XSSFWorkbook(file);
                }
            }
            else
            {
                MessageBox.Show("不支持的文件格式。");
                return;
            }

            ISheet sheet = workbook.GetSheetAt(0);
            IRow headerRow = sheet.GetRow(0);
            foreach (ICell headerCell in headerRow)
            {
            dataTable.Columns.Add(headerCell.ToString());
            }
            for (int rowIndex = 1; rowIndex <= sheet.LastRowNum; rowIndex++)
            {
                IRow dataRow = sheet.GetRow(rowIndex);
                if (dataRow == null)
                {
                    dataTable.Rows.Add(dataTable.NewRow());
                }
                else
                {
                    if (dataRow.GetCell(rowIndex) != null)
                    {                       
                    }                    
                    DataRow newRow = dataTable.NewRow();

                    for (int cellIndex = 0; cellIndex < headerRow.Cells.Count; cellIndex++)
                    {                        
                        ICell cell = dataRow.GetCell(cellIndex);
                        if (cell != null)
                        {
                            newRow[cellIndex] = cell.ToString();
                        }
                    }
                    dataTable.Rows.Add(newRow);
                }
            }                
            dataGridView.DataSource = null;//解决Datagridview列顺序莫名其妙改变的问题。
            dataGridView.DataSource = dataTable;            
        }

问题补充:

发现获取headerCell值时,可显示的列名称值为{},不可显示的列名称没有值,直接跳过了。

xcbjnyx的主页 xcbjnyx | 菜鸟二级 | 园豆:258
提问于:2023-11-07 14:45
< >
分享
最佳答案
1

在你的代码中,问题可能出现在数据读取阶段,尤其是在填充 DataTable 的部分。更准确地说,在 for 循环中对行的读取和数据处理部分可能存在问题。

可能的问题点:
空行处理不完整: 在 if (dataRow == null) 中添加了对空行的处理,但是处理逻辑不够完整,这可能导致在数据行为空时直接添加一个空行,而不是处理表头有空单元格的情况。

空单元格处理: 在你的代码中,没有处理空单元格的情况。如果表格中存在空单元格,可能会导致空单元格后的列索引错位,因为数据行的单元格索引可能和表头行的索引不匹配。

数据行的索引使用有问题: 你在读取数据的地方使用了 dataRow.GetCell(rowIndex),这个地方可能有问题。应该使用 dataRow.GetCell(cellIndex) 来获取每一列的单元格。

数据行添加逻辑问题: 在向 dataTable 添加新行的地方可能存在问题,可能需要在确认数据行不为空的情况下再添加。

建议的修正:
检查空单元格问题。考虑在读取数据时,使用 dataRow.GetCell(cellIndex) 而不是 dataRow.GetCell(rowIndex)。

为了处理空单元格,应该确保在找到空单元格时,跳过数据的索引而不是直接添加新行。

考虑使用 StringCellValue 或其他合适的方法从单元格中获取数据而不是简单地使用 ToString(),以防止出现问题。

确保逻辑对齐,处理表头和数据行的对应关系。

下面是你代码的修改建议:

for (int rowIndex = 1; rowIndex <= sheet.LastRowNum; rowIndex++)
{
IRow dataRow = sheet.GetRow(rowIndex);

if (dataRow != null) // 进行非空判断,避免处理空行
{
    DataRow newRow = dataTable.NewRow();

    for (int cellIndex = 0; cellIndex < headerRow.Cells.Count; cellIndex++)
    {
        ICell cell = dataRow.GetCell(cellIndex);
        if (cell != null)
        {
            // 使用适当的方法获取单元格的值而不是简单的 ToString()
            newRow[cellIndex] = cell.StringCellValue; // 或其他合适的方法
        }
        else
        {
            // 处理空单元格,可以选择跳过或者赋予特定值
            newRow[cellIndex] = string.Empty; // 或者赋予其他默认值
        }
    }
    dataTable.Rows.Add(newRow);
}

}
在修改后的代码中,根据数据行中的单元格数量迭代处理,同时处理了空单元格的情况。最后将处理好的行添加到 dataTable 中。这样应该更好地处理了空单元格问题,避免了因数据行空值或缺失导致的列错位情况。

收获园豆:160
路小乙 | 菜鸟二级 |园豆:469 | 2023-11-07 17:12

感谢解惑,感谢建议。

 

另:刚刚试了一下代码,还要将纯数字的单元格设为string类型,才能不报错。

 

 

1 if (cell != null)
2 
3 {
4 // 使用适当的方法获取单元格的值而不是简单的 ToString()
5 cell.SetCellType(CellType.String);//将纯数字单元格转换成string类型
6 newRow[cellIndex] = cell.StringCellValue; // 或其他合适的方法
7 }

 

 

xcbjnyx | 园豆:258 (菜鸟二级) | 2023-11-08 10:03
其他回答(1)
0

excel本来就挺乱的,他是为了兼容各种操作习惯。你代码也应该同时兼容null、DbNull、string.Empty

乙苯道 | 园豆:226 (菜鸟二级) | 2023-11-07 16:35

了解,但是心里还是疑惑,同样都是在Excel表格中直接插入的列,有的可以在datagridview显示,有的不行?

支持(0) 反对(0) xcbjnyx | 园豆:258 (菜鸟二级) | 2023-11-07 16:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册