【问题标题】:OpenXML - Not reading a blank Cell from a row C#OpenXML - 不从行 C# 中读取空白单元格
【发布时间】:2017-05-02 05:22:18
【问题描述】:
我有一个 .xlsx 文件,其中 3 列 SrNumber、Name、Active 分别位于 A、B 和 C 列。
我正在使用以下问题的答案中给出的源代码在 DataTable 中读取此文件的内容
From Excel to DataTable in C# with Open XML
我也做了 Sourabh 建议的修改
当我的内容如下时效果很好
A B C
1 SrNumber Name Active
2 1 test1 Yes
3 2 test2 Yes
4 3 test3 Yes
5 4 test4 Yes
现在,当我尝试在第 6 位添加一行时,我只在 B6 和 C6 单元格中输入数据。 我没有碰过A6 Cell。
运行该代码后,我的 DataTable 填充如下
您可以看到在 B6 中输入的值在第一列,在 C6 中输入的值在第二列。
同样row.Descendants<Cell>() 只为新输入的行返回 2 个单元格。
如果对源代码进行任何修改,请告诉我。
【问题讨论】:
标签:
c#
openxml
openxml-sdk
【解决方案1】:
//Read the first Sheet from Excel file.
IXLWorksheet workSheet = workBook.Worksheet(1);
//Create a new DataTable.
DataTable dt = new DataTable();
//Loop through the Worksheet rows.
bool firstRow = true;
foreach (IXLRow row in workSheet.Rows())
{
//Use the first row to add columns to DataTable.
if (firstRow)
{
foreach (IXLCell cell in row.Cells())
{
dt.Columns.Add(cell.Value.ToString());
}
firstRow = false;
}
else
{
//Add rows to DataTable.
dt.Rows.Add();
int i = 0;
//for (IXLCell cell in row.Cells())
for (int j=1;j<= dt.Columns.Count;j++)
{
if (string.IsNullOrEmpty(row.Cell(j).Value.ToString()))
dt.Rows[dt.Rows.Count - 1][i] = "";
else
dt.Rows[dt.Rows.Count - 1][i] = row.Cell(j).Value.ToString();
i++;
}
}
}
【解决方案2】:
下面的代码应该可以为您解决问题。 CellReferenceToIndex 非常重要,当我们遇到空单元格时,它会计算实际的单元格索引:
using System;
using System.Data;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
public static DataTable ReadAsDataTable(string fileName)
{
DataTable dataTable = new DataTable();
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(fileName, false))
{
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
string relationshipId = sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
Worksheet workSheet = worksheetPart.Worksheet;
SheetData sheetData = workSheet.GetFirstChild<SheetData>();
IEnumerable<Row> rows = sheetData.Descendants<Row>();
foreach (Cell cell in rows.ElementAt(0))
{
dataTable.Columns.Add(GetCellValue(spreadSheetDocument, cell));
}
foreach (Row row in rows)
{
DataRow dataRow = dataTable.NewRow();
for (int i = 0; i < row.Descendants<Cell>().Count(); i++)
{
Cell cell = row.Descendants<Cell>().ElementAt(i);
int actualCellIndex = CellReferenceToIndex(cell);
dataRow[actualCellIndex] = GetCellValue(spreadSheetDocument, cell);
}
dataTable.Rows.Add(dataRow);
}
}
dataTable.Rows.RemoveAt(0);
return dataTable;
}
private static string GetCellValue(SpreadsheetDocument document, Cell cell)
{
SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
string value = cell.CellValue.InnerXml;
if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
{
return stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
}
else
{
return value;
}
}
private static int CellReferenceToIndex(Cell cell)
{
int index = 0;
string reference = cell.CellReference.ToString().ToUpper();
foreach (char ch in reference)
{
if (Char.IsLetter(ch))
{
int value = (int)ch - (int)'A';
index = (index == 0) ? value : ((index + 1) * 26) + value;
}
else
return index;
}
return index;
}