【问题标题】:How to know if a cell has an error in the formula in C#如何知道单元格是否在 C# 中的公式中有错误
【发布时间】:2011-01-26 08:27:50
【问题描述】:

在 Excel 公式中,您可以使用 =ISERR(A1)=ISERROR(A1)

在 VBA 宏中,您可以使用 IsError(sheet.Cells(1, 1))

但是使用 VSTO Excel Addin 项目,我没有在 Microsoft.Office.Interop.Excel API 下找到类似的功能。我只想知道单元格中是否有错误,我对错误的类型并不感兴趣。

我目前的解决方法是对所有现有的错误消息执行此操作。:

if (((Range)sheet.Cells[1, 1]).Text == "#N/A" || ...)

有没有更好的方法来做到这一点。 API中有一个简单的函数吗?

【问题讨论】:

  • (sheet.Cells[1,1] as Range).Text 看起来更好。
  • 它看起来确实更好,但是如果由于某种原因 Cells[1,1] 不是 Range 类型,那么我们将有 NullReferenceException 而不是 InvalidCastException。在这种情况下,我更喜欢获得更精确的异常类型而不是提高可读性。

标签: c# excel vsto


【解决方案1】:

在 .NET 中处理 CVErr 值是一个非常棘手的主题。问题是 .NET(正确地)认为 CVErr 在错误处理方面已经过时。然而,CVErr 值仍然在 Excel 单元格中使用,因此对于 Excel 自动化来说这是一个相当大的遗漏。

幸运的是,有一个解决方法。检查 CVErr 值的方法是检查单元保存的数据类型。如果保存的值键入为整数 (Int32),则保存的值是 CVErr。 (请注意,单元格中保存的数值通常输入为 Double,只有 CVerr 值可以输入为 Integer。)

也就是说,在最简单的层面上,要测试 CVErr 值,您需要做的就是使用以下函数:

bool IsXLCVErr(object obj)
{
    return obj is Int32;
}

如果您需要检查特定的 CVErr 值(例如,#N/A),那么您将首先检查以确保数据类型是整数 (Int32),然后检查单元格保存的特定值,根据这张表:

  • -2146826281 = #DIV/0!
  • -2146826246 = #N/A
  • -2146826245 = #GETTING_DATA
  • -2146826259 = #NAME?
  • -2146826288 = #NULL!
  • -2146826252 = #NUM!
  • -2146826265 = #REF!
  • -2146826273 = #VALUE!

例如,您的代码可能如下所示:

enum CVErrEnum : Int32
{
    ErrDiv0 = -2146826281,
    ErrGettingData = -2146826245,
    ErrNA = -2146826246,
    ErrName = -2146826259,
    ErrNull = -2146826288,
    ErrNum = -2146826252,
    ErrRef = -2146826265,
    ErrValue = -2146826273
}

bool IsXLCVErr(object obj)
{
    return (obj) is Int32;
}

bool IsXLCVErr(object obj, CVErrEnum whichError)
{
    return (obj is Int32) && ((Int32)obj == (Int32)whichError);
}

几年前我写了一篇详细的两部分文章:

文章是为 VB.NET 编写的,但原理与 C# 完全相同。

【讨论】:

  • 这种答案让人们希望 SO 有“一天一次的超级投票”功能
  • 谢谢 Mike,这是我一整天都在寻找的信息。返回的行数很奇怪,并且没有意识到 VBA 对待具有 CVErr 的单元格与 .net 不同(它只是将它们视为 Int 值。
  • 很高兴这有帮助!几年前,当我第一次遇到这个问题时,它真的让我陷入了困境。这是一个看似不可能解决的问题。所以一旦我弄清楚如何处理它,我只需要写下来。
  • 最后,我认为 code4life 的解决方案正是我想要的。无论如何,感谢您提供有关该主题的所有好信息。
  • 好的,但我不确定您检查的答案是否正确。例如,code4life 的答案不会选择 #N/A 值。但它可以很容易地纠正:代码应该使用WorksheetFunction.IsError。我无法反驳这种简单性,但我现在还在上面的解释中添加了一些代码,以便您可以看到它最终也非常简单。如果您需要获取一个特定的 CVErr 值(除了#N/A,可以通过WorksheetFunction.IsNa 获取),那么我在这里提出的方法确实是唯一的办法。
【解决方案2】:

您可以使用WorksheetFunction 方法:

Globals.ThisAddIn.Application.WorksheetFunction.IsErr(...)

[Your Excel Object].WorksheetFunction.IsErr(...)

IsErr 在语义上与 Excel 工作表函数相同,只是在实际值中传递单元格引用 - AFAIK。

【讨论】:

  • 快速说明:WorksheetFunction.IsErr 将根据设计为 #N/A 值返回 false。因此,要使用这种方法,应该改用WorksheetFunction.IsError。如果您需要获取一个特定的 CVErr 值,那么您可以使用WorksheetFunction.IsNA 获取#N/A 值,但是对于任何其他特定的CVErr 类型,您必须使用我的方法'如下所述。
  • 感谢您的澄清,迈克!
  • 由于某种原因 WorksheetFunction.IsError() 对我不起作用,但其他解决方案(is Int32 的测试)确实有效。
  • 请注意,如果您已经拥有单元格值,则使用 Application.WorksheetFunction 与检查值的类型相比非常慢,因为它是一个 COM 互操作函数,必须分派到 excel 应用程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
相关资源
最近更新 更多