本人小白在进行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值时,可显示的列名称值为{},不可显示的列名称没有值,直接跳过了。
在你的代码中,问题可能出现在数据读取阶段,尤其是在填充 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 中。这样应该更好地处理了空单元格问题,避免了因数据行空值或缺失导致的列错位情况。
感谢解惑,感谢建议。
另:刚刚试了一下代码,还要将纯数字的单元格设为string类型,才能不报错。
1 if (cell != null) 2 3 { 4 // 使用适当的方法获取单元格的值而不是简单的 ToString() 5 cell.SetCellType(CellType.String);//将纯数字单元格转换成string类型 6 newRow[cellIndex] = cell.StringCellValue; // 或其他合适的方法 7 }
excel本来就挺乱的,他是为了兼容各种操作习惯。你代码也应该同时兼容null、DbNull、string.Empty
了解,但是心里还是疑惑,同样都是在Excel表格中直接插入的列,有的可以在datagridview显示,有的不行?