为什么 OpenXML 读取行两次

2023-12-19

我计算两个工作表中的行数,如下所示:

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++;
}

对于两个工作表count_first and count_second我得到的数据是数据行数的两倍。为什么会这样?它到底意味着什么?是不是意味着OpenXML解析每个列表两次?

EDIT

好吧,我找到了解决方案。我想,为了立即获得它,你应该将这种神圣的知识保存在某个秘密的地方。所以,这里是:

while (reader.Read())
{
    if (reader.ElementType == typeof(Row))
    {
        do
        {
            count_first++;
        }   while (reader.ReadNextSibling());
    }
}

您得到两倍计数的原因是由于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”命名空间为前缀。为了便于阅读,我已将其删除。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 OpenXML 读取行两次 的相关文章

  • 带有 ASP.NET 按钮回发的 jQuery UI 对话框

    我的 ASP NET 页面上有一个运行良好的 jQuery UI 对话框 jQuery function jQuery dialog dialog draggable true resizable true show Transfer hi
  • 如何使用不同的基本路径托管 Blazor WebAssembly 应用程序

    我有一个 Blazor Webassemble NET 托管应用程序 在我们托管它的服务器上 应用程序的基本路径将是mydomain com coolapp 因此 为了尝试让应用程序在服务器上正确呈现 我一直遵循本页 应用程序基本路径 部分
  • 来自 double 的 static_cast 可以优化分配给 double 吗?

    我偶然发现了一个我认为不必要的功能 并且通常让我感到害怕 float coerceToFloat double x volatile float y static cast
  • 加载 QPixmap 数据的更好方法

    更好的方法来做到这一点 没有QImage QImage image width height QImage Format RGB888 memcpy image bits m frameRGB gt data 0 height width
  • 自己绘制的WPF自定义滑块

    这是我关于堆栈溢出的第一个问题 所以不要踢它 我在尝试创建 Mac 风格的滑块控件时遇到问题 我已经发现这个解决方案 http www codeproject com KB miscctrl MAC Slider aspx我已经在我的解决方
  • DateTime.ParseExact - 为什么 yy 变成 2015 而不是 1915

    为什么 NET 假定以下年份是 2015 年 而不是 1915 年 var d DateTime ParseExact 20 11 15 dd MM yy new CultureInfo en GB 我想 它会尝试接近 但其背后是否有合理的
  • 更改私有模块片段是否会导致模块重新编译?

    On 此页面有关 C 20 模块功能 https www modernescpp com index php c 20 modules private module fragment and header units 我发现了这样的说法 借
  • Excel VBA 循环遍历 10,000 组行,每组包含 20 行

    如何将当前按行循环的 Excel VBA 代码转换为循环 20 行集 据我了解 Step函数可能与以下行一起使用 Range V1 Value Application Index vInput1 r 0 但是 我不确定如何修改代码以循环遍历
  • main.cpp 是必需的吗?

    我试图编译一个程序cmake 我最终删除了我的main cpp文件 我刚刚将其复合到另一个包含我的项目名称的文件中 即 我刚刚将主函数剪切并粘贴到该文件中 问题是我有一个main cpp未发现错误 不确定是否在C 一个名为main cpp是
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • C++网络序列化[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一种将 C 数据包序列化为网络流的解决方案 我在这里看到很多帖子提到人们 ACE 谷歌协议缓
  • Clang 5.0 上的 vsprintf 和 vsnprintf [-Wformat-nonliteral] 警告

    我有这段代码 static void err doit int errnoflag int level const char fmt va list ap int errno save unsigned long n char buf MA
  • 在一个解决方案中调用不同项目的方法

    1 个解决方案中有 3 个项目 我对第一个项目中的主文件进行的主要操作 但是我需要调用第三个项目中的方法并使用类 例如 第三个项目有 public DataClasses1DataContext base global WindowsFor
  • g++ / gcc 是否支持 C++20 新的atomic_flag 功能?

    根据参考参数 https en cppreference com w cpp atomic atomic flag c 20 有丰富的 对我来说有用的 支持atomic flag运营 然而 目前尚不清楚 gcc 是否支持这些功能 它们在任何
  • 让 Windows 尝试读取文件

    我正在对 Windows 文件系统进行某种封装 当用户请求打开文件时 Windows 调用我的驱动程序来提供数据 在正常操作中 驱动程序返回缓存的文件内容 但是 在某些情况下 实际文件没有缓存 我需要从网络下载它 问题是是否有可能让 Win
  • C# 多维数组解析

    我有一个多维数组 内容在调试器中看起来像这样 数组设置为 String s new String 6 4 A B Yes C A B Yes C A B No C A B Yes C A B Yes C A B Yes C A B No C
  • 在多线程环境中捕获信号

    我有一个大型程序 需要尽可能具有弹性 并且有大量线程 我需要捕获所有信号SIGBUS SIGSEGV 并在必要时重新初始化有问题的线程 或者禁用该线程以继续减少功能 我的第一个想法是做一个setjump 然后设置信号处理程序 可以记录问题
  • 为什么存在系统调用

    我一直在阅读有关系统调用及其在 Linux 中如何工作的内容 我还有更多的阅读要做 但我读过的一件事都没有回答 那就是 为什么我们需要系统调用 我知道系统调用是用户空间程序要求内核执行某些操作的请求 但我的问题基本上是 为什么用户空间程序本
  • C++ 中的析构函数

    我的 AB h 文件中有一个构造函数 class AB private int i public AB i 0 constructor AB i 0 destructor virtual void methodA unsigned int
  • NHibernate:无状态会话错误消息无法获取代理

    我正在使用 nHibernate 无状态会话来获取对象 更新一个属性并将对象保存回数据库 我不断收到错误消息 无状态会话无法获取代理 我在其他地方有类似的代码 所以我不明白为什么这不起作用 有谁知道问题可能是什么 我正在尝试更新Screen

随机推荐