您得到两倍计数的原因是由于OpenXmlReader
读取每个元素。读者将打开和关闭节点视为独立的项目,可以通过检查来区分它们IsStartElement https://msdn.microsoft.com/en-us/library/documentformat.openxml.openxmlreader.isstartelement%28v=office.14%29.aspx and IsEndElement https://msdn.microsoft.com/en-gb/library/documentformat.openxml.openxmlreader.isendelement%28v=office.14%29.aspx特性。
为了演示这一点,您可以运行如下命令:
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");
}
}
}
对于具有两行和两列的工作表,这将产生如下*的输出(为了便于阅读,我突出显示了行):
行 真 假
单元格 真 假
单元格值 True False
单元格值 假 真
细胞 假 真
单元格 真 假
单元格值 True False
单元格值 假 真
细胞 假 真
行 假 真
行 真 假
单元格 真 假
单元格值 True False
单元格值 假 真
细胞 假 真
单元格 真 假
单元格值 True False
单元格值 假 真
细胞 假 真
行 假 真
有两种方法可以解决此问题,具体取决于您想要如何阅读文档。第一种方法(正如您在答案中指出的那样)是通过调用移动到下一个兄弟姐妹ReadNextSibling
- 这本质上是“跳转”结束元素(以及该元素的任何子元素)Row
)。改变上面的例子来使用ReadNextSibling
in the do
loop:
do
{
Console.WriteLine("{0} {1} {2}",
reader.ElementType,
reader.IsStartElement,
reader.IsEndElement);
} while (reader.ReadNextSibling());
您将得到以下输出*:
行 真 假
行 真 假
第二种方法是只计算开始元素(或者实际上是结束元素;只是不是两者):
while (reader.Read())
{
if (reader.ElementType == typeof(Row) && reader.IsStartElement)
{
count_first++;
}
}
选择哪一个取决于您是否想阅读Cell
价值观和how你想阅读它们(SAX 或 DOM)。
* 实际上,每一行都以“DocumentFormat.OpenXml.Spreadsheet”命名空间为前缀。为了便于阅读,我已将其删除。