我计算两个工作表中的行数,如下所示:
foreach (WorksheetPart worksheetPart in workbookPart.WorksheetParts)
{
OpenXmlPartReader reader = new OpenXmlPartReader(worksheetPart);
if (count == 0)
{
while (reader.Read())
{
if (reader.ElementType == typeof(Row))
{
count_first++;
}
}
}
else if (count == 1)
{
while (reader.Read())
{
if (reader.ElementType == typeof(Row))
{
count_second++;
}
}
}
count++;
}
Run Code Online (Sandbox Code Playgroud)
count_first
对于和中的两个工作表,count_second
我得到的数据是数据行数的两倍。为什么会这样?它实际上意味着什么?这是否意味着OpenXML
解析每个列表两次?
编辑
好吧,我找到了解决方案。我想,为了立即获得它,你应该将这种神圣的知识保存在某个秘密的地方。所以,这里是:
while (reader.Read())
{
if (reader.ElementType == typeof(Row))
{
do
{
count_first++;
} while (reader.ReadNextSibling());
}
}
Run Code Online (Sandbox Code Playgroud)
您获得两倍计数的原因是由于读取OpenXmlReader
每个元素的方式所致。读者将打开和关闭节点视为独立的项目,可以通过检查IsStartElement
和IsEndElement
属性来区分它们。
为了演示这一点,您可以运行如下命令:
using (OpenXmlReader reader = OpenXmlReader.Create(worksheetPart))
{
while (reader.Read())
{
if (reader.ElementType == typeof(Row))
{
do
{
Console.WriteLine("{0} {1} {2}",
reader.ElementType,
reader.IsStartElement,
reader.IsEndElement);
} while (reader.Read());
Console.WriteLine("Finished");
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于具有两行和两列的工作表,这将产生如下*的输出(为了便于阅读,我突出显示了行):
行 True False
Cell True False
CellValue True False
CellValue False True
Cell False True Cell
True
False CellValue True False
CellValue False True Cell False True Row False True行 True False Cell True False CellValue True False CellValue False True Cell False True Cell True False CellValue True False CellValue False True 单元格 False True行 False True
有两种方法可以解决此问题,具体取决于您想要如何阅读文档。第一种方法(正如您在答案中指出的那样)是通过调用移动到下一个同级元素ReadNextSibling
- 这本质上是“跳转”结束元素(以及 的任何子元素Row
)。将上面的示例更改为ReadNextSibling
在循环中使用do
:
do
{
Console.WriteLine("{0} {1} {2}",
reader.ElementType,
reader.IsStartElement,
reader.IsEndElement);
} while (reader.ReadNextSibling());
Run Code Online (Sandbox Code Playgroud)
您将得到以下输出*:
行 真 假
行 真 假
第二种方法是只计算开始元素(或者实际上是结束元素;只是不是两者):
while (reader.Read())
{
if (reader.ElementType == typeof(Row) && reader.IsStartElement)
{
count_first++;
}
}
Run Code Online (Sandbox Code Playgroud)
您选择哪一种取决于您是否希望读取这些Cell
值以及您希望如何读取它们(SAX 或 DOM)。
* 实际上,每一行都以“DocumentFormat.OpenXml.Spreadsheet”命名空间为前缀。为了便于阅读,我已将其删除。
归档时间: |
|
查看次数: |
740 次 |
最近记录: |