【问题标题】:Performant Check if Sheet is Error Free in C# Interop性能检查工作表在 C# 互操作中是否无错误
【发布时间】:2019-10-14 17:57:02
【问题描述】:

我们需要在大约 300 万个单元格的大型工作簿中查找公式错误。性能至关重要。我们已经围绕特殊单元实现了一个包装函数,它允许我们在该工作表上没有找到错误单元的情况下捕获异常。类似于:

Handling "No cells were found." Error in Excel

但问题是,当抛出 COM 异常时,检查变得非常缓慢。更具体地说,当工作表上出现一个错误时,我们记录的执行时间在 1 到 4 毫秒之间。当错误被抛出时,我们正在查看大约 80 毫秒。

有没有人有任何创造性的快速替代方法来检查不存在的错误?

我们的代码:

try
{
  dynamic cellsWithErrors = cells.SpecialCells(cellType, valueType);
  return cellsWithErrors;
}
catch (COMException)
{
  return null;
}         

注意事项:

  • 发现存在的错误很好,因此无需关注这一点。

  • 我已经发现使用动态类型而不是 Range 类型可以适度加速

  • 我们的检查会遍历整个工作簿中的所有工作表。因此,我们也很乐意看到任何适用于工作簿的解决方案,但怀疑它是否存在。

  • 我们将其编写为 VSTO 插件的一部分并使用互操作层。

已经考虑的解决方案

我们可以将整个范围读取为值并对其进行迭代,但希望看看是否还有其他内容。因为在出现错误的情况下,这会变慢。

当前想法

所以难题归结为这一点。一方面,SpecialCells 在找到结果时非常快。但是抛出异常会导致 20 到 80 倍的减速。另一方面,读取纸张的整个使用范围在性能方面非常一致:我会说它与单元格的数量成线性关系,并且一次性支付少量的固定首付。现在,通过检查单元格值,可能会发现错误,在这里使用 Mike Rosenblum 的答案:How to know if a cell has an error in the formula in C#。如果是这样,那么我们将有另一种方法来检查错误。

然后的想法是编写一个主函数,该函数以相关工作表的大小为中心。如果它是一个非常大的工作表(我认为我们有一个大约有 200 万个单元格的工作表),那么我们不妨只使用 SpecialCells 并接受发生异常的成本。但是对于较小的工作表,异常的成本超过了在整个范围内读取并在内存中遍历它的成本,那么我们应该只做后者。

对于这种方法,我们需要确定的关键是交叉点是什么:SpecialCells 从哪里开始优于读取和迭代?我们可能还想利用我们自己对工作簿的了解来启发式地猜测哪些工作表可能有错误,哪些没有。如果我们开发一个并且我有时间,我会发布一个答案。

【问题讨论】:

    标签: c# performance excel-interop


    【解决方案1】:

    事实证明,来自 OP 问题的性能统计数据是错误的。他们被记录在调试模式下运行。所以这个问题的真正答案是:不要在调试模式下进行性能测试。呃。在调试模式下,异常处理必须有一些巨大的成本,尽管我们注意到我的机器与我队友的机器有很大的不同,所以也许这是我的一些本地调试设置。我相信其他人可以对此发表更多评论。

    在调试模式之外运行时,SpecialCells 函数的 true 性能平均为 4 毫秒。这对于我们的用例来说是完全可以接受的。然而,当我们发现这一点时,我们已经重构了我们的代码,并且实际上得到了进一步的性能提升......

    银色衬里

    最后,我们采用了混合解决方案。如果有问题的工作表有超过 200_000 个单元格,我们只使用 SpecialCells 标注,平均花费 4 毫秒。但是,如果工作表的单元格数量少于此数量,我们会读取整个使用范围并遍历其所有单元格,通过查看值来检查错误类型,这与 Mike Rosenblum 的回答类似:How to know if a cell has an error in the formula in C#。对我们而言,循环遍历那些

    【讨论】:

      猜你喜欢
      • 2012-08-01
      • 2018-09-08
      • 1970-01-01
      • 2013-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多