C# 为什么OpenXML读取行两次
我在两个工作表中计算行数,如下所示:C# 为什么OpenXML读取行两次,c#,excel,openxml,C#,Excel,Openxml,我在两个工作表中计算行数,如下所示: foreach (WorksheetPart worksheetPart in workbookPart.WorksheetParts) { OpenXmlPartReader reader = new OpenXmlPartReader(worksheetPart); if (count == 0) { while (reader.Read()) { if (reader.El
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++;
}
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");
}
}
}
对于count\u first
和count\u second
中的两个工作表,我得到的数据是有数据行的两倍。这是为什么?它到底意味着什么?这是否意味着OpenXML
会对每个列表进行两次解析
编辑
我找到了解决办法。我想,为了马上得到它,你应该把这些神圣的知识藏在某个秘密的地方。这就是:
while (reader.Read())
{
if (reader.ElementType == typeof(Row))
{
do
{
count_first++;
} while (reader.ReadNextSibling());
}
}
这与预期的效果一样:
while (reader.Read())
{
if (reader.ElementType == typeof(Row))
{
do
{
count_first++;
} while (reader.ReadNextSibling());
}
}
得到两倍计数的原因是
OpenXmlReader
读取每个元素的方式。读取器将打开和关闭节点视为独立项,可以通过检查和属性来区分这些独立项
要演示这一点,您可以运行如下操作:
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++;
}
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");
}
}
}
这将为具有两行两列的工作表生成以下*行的输出(为了便于阅读,我突出显示了这些行):
行真假单元格真假
CellValue True False
CellValue False True
单元格假-真
单元格真假
CellValue True False
CellValue False True
单元格假-真
行假-真
行真假
单元格真假
CellValue True False
CellValue False True
单元格假-真
单元格真假
CellValue True False
CellValue False True
单元格假-真
行假真 根据您阅读文档的方式,有两种方法可以解决此问题。第一种方法(正如您在回答中指出的那样)是通过调用
ReadNextSibling
移动到下一个同级-这实质上是“跳转”结束元素(以及行的任何子元素
)。将上述示例更改为在do
循环中使用ReadNextSibling
:
do
{
Console.WriteLine("{0} {1} {2}",
reader.ElementType,
reader.IsStartElement,
reader.IsEndElement);
} while (reader.ReadNextSibling());
您将获得以下内容的输出*:
行真假行真假 第二种方法是只计算开始元素(或者实际上是结束元素;只是不能同时计算两者): 选择哪一个取决于您是否希望读取
单元格
值以及如何读取它们(SAX或DOM)
*实际上,每一行的前缀都是名称空间“DocumentFormat.OpenXml.Spreadsheet”。为了便于阅读,我已将其删除。如果您有答案,请将其作为答案发布,而不是对您的问题进行编辑。此外,在延迟一段时间后,您可以将其标记为已接受的答案。在这里,回答自己的问题是完全可以接受的行为。但我们知道,当问题得到公认的答案时,问题已经得到了令人满意的处理(目前,您的问题似乎仍未得到回答)