我在c sharp中运行一些基于openXML的代码,这些代码停留在第一行数据上并且一次又一次地循环它。我很清楚我需要将行变量合并到混合中,但尝试了各种方法无济于事。有人对此有任何想法吗?
在下面的代码块中,sst.ChildElements [7] .InnerText返回第一行第7列的内容,但每次行循环来自同一个CELL的内容!我想进入下一行: - (
string fileName = @"c:\temp\accountData.xlsx";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false))
{
WorkbookPart workbookPart = doc.WorkbookPart;
SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
SharedStringTable sst = sstpart.SharedStringTable;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
Worksheet sheet = worksheetPart.Worksheet;
var cells = sheet.Descendants<Cell>();
var rows = sheet.Descendants<Row>();
Console.WriteLine("Row count = {0}", rows.LongCount());
Console.WriteLine("Cell count = {0}", cells.LongCount());
CompanyProvider cp = _db.GetCompanyProvider();
int i = 0;
// Or... via each row
foreach (Row row in rows.ToList())
{
if (i == 0)
i = i + 1;
else
{
CustomerAddress customerAddress = new CustomerAddress();
customerAddress.AddressLine1 = sst.ChildElements[7].InnerText; // Code hidden for brevity
i = i + 1;
}
}
}
}
答案 0 :(得分:0)
通过行进行交互的基本算法涉及两个循环。一个用于行,另一个用于单元格。
假设您有一张工作表。
这是你获取行集合的方式。
IEnumerable<Row> rows = worksheet.Descendants<Row>();
连续你有一组细胞。
所以你需要在行上有第一个循环
foreach (Row row in rows)
{
}
在这里,您可以获得一行
的单元格集合IEnumerable<Cell> cells = row.Descendants<Cell>()
然后你可以遍历内循环中的单元格
foreach (Cell cell in cells)
{
//Here goes the logic of reading cell value
}
答案 1 :(得分:0)
在下面的代码块中,sst.ChildElements [7] .InnerText返回第一行第7列的内容,但每次行循环来自同一个CELL的内容!
这是因为您始终在SharedStringsTable
(您的7
变量)中读取元素sst
中的值,而不是Row
中元素7中的值(你的row
变量。)
共享字符串表是OpenXML中使用的一种机制,用于防止重复数据出现在单元格中(以减小文件大小)。它不是直接包含字符串值的单元格,而是包含一个整数,它是共享字符串表的索引。这样,如果一个字符串在Excel文件中重复多次,它只存储一次但对该字符串有很多引用。
您可以通过查看DataType
属性来判断Cell
对象是否包含共享字符串索引(请注意,字符串可以存储在线和其他数字等数据类型总是以内联方式存储。
如果单元格确实包含共享字符串索引,那么您可以使用该值来索引sst
属性以获取正确的内容:
sst.ChildElements[<cell content here>].InnerText
要按索引获取行单元格,您可以获取Cell
的子Row
,然后使用Enumerable<T>.ElementAt
方法获取索引中的Cell
需要:
row.Elements<Cell>().ElementAt(7); //gives the 8th Cell in row - read the "HOWEVER" section!!
使用上述内容,您的foreach
就会变成:
foreach (Row row in rows.ToList())
{
if (i == 0)
i = i + 1;
else
{
//get the cell at index 7
Cell cell = row.Elements<Cell>().ElementAt(7); //read the warning below
//check the type
if (cell.DataType != null && cell.DataType == CellValues.SharedString)
{
//it's a shared string so use the cell inner text as the index into the
//shared strings table
Console.WriteLine(sst.ChildElements[int.Parse(cell.InnerText)].InnerText);
}
else
{
//it's NOT a shared string, output the value directly
Console.WriteLine(cell.InnerText);
}
i = i + 1;
}
}
<强>无论其... 强>
上面的代码将起作用但是,按照您尝试的方式索引单元格是容易出错的。 OpenXML模式允许从文件中省略空单元格(和行)。这意味着如果某个地方有一个空单元格,您可能最终得到错误的值。
在该文件上运行上述代码会产生输出:
9
8
请注意,在解析的第一行,我们最终会从I2
获取值,但在我们读取的第二行,我们从H3
获取值。我们读取的第一行是一个(假设第7个索引表示你想要列H
),因为该行的XML中没有列B
。这就是为什么你会发现读取Excel文件的大多数代码使用循环迭代单元格的原因。