【问题标题】:Whats the difference between WorksheetFunction.IsNumber() and IsNumeric() in VBA?VBA 中的 WorksheetFunction.IsNumber() 和 IsNumeric() 有什么区别?
【发布时间】:2018-07-27 02:02:02
【问题描述】:

在 VBA 中使用这两个函数有什么不同?使用一个比另一个有速度优势吗?

Application.WorksheetFunction.IsNumber(myVar)
IsNumeric(myVar)

【问题讨论】:

  • 如果您正在寻找使用其中一个的理由,可以在 VBA Rubberducking 聊天 here 和 Rubberduck GitHub 存储库上的 relevant closed issue 中进行讨论。如果等效,请使用 VBA 函数。

标签: vba excel function


【解决方案1】:

IsNumeric是位于VBA.Information模块中的VBA标准库函数,如IsArrayIsDateIsErrorErrVarType等:

作为 VBA 标准库的一部分,无论宿主应用程序如何,它都能正常工作:可以安全地假定标准库存在于运行 VBA 的机器上。

另一方面,Application.WorksheetFunction.IsNumber 位于 Microsoft Excel 对象模型库中:

因此,代码只有在引用 Excel 类型库时才能工作。如果您已经在 Excel 中,那不是问题。但是,如果您在 Word 中,并且想要使用在给定的 String 是数字时返回 Boolean 的函数,您不想仅仅为此引用整个 Excel 类型库。

WorksheetFunction 接口是通往 Excel 计算引擎的门户:有了它,您可以编写 VBA 代码,现在可以使用 INDEX/MATCH 来处理精心制作的纯 VBA 数组 - 这非常棒。但不能保证 Excel 的计算引擎的工作方式与 VBA 的工作方式完全相同。如果你想遵守 Excel 的规则,请使用WorksheetFunction

我可能会认为 VBA.Information.IsNumericExcel.WorksheetFunction.IsNumber 快:我可能是错的,但似乎只有 VBA 标准库涉及更少的移动部件。

但唯一的办法是:

你有两匹马 - 与它们比赛!

;-)

【讨论】:

  • ?IsNumeric("999") 为真,但?Application.WorksheetFunction.IsNumber("999") 为假。
  • 那是因为“999”不是一个数字——它是一个字符串。 IsNumber 检查变体的类型,而 IsNumeric 检查是否可以转换。 msdn.microsoft.com/en-us/vba/excel-vba/articles/…The value arguments of the IS functions are not converted. For example, in most other functions where a number is required, the text value "19" is converted to the number 19. However, in the formula ISNUMBER("19"), "19" is not converted from a text value, and the ISNUMBER function returns FALSE.
  • @JerryJeremiah 需要注意的是,这取决于您是使用.Value(将其转换为Variant)从单元格中提取数据还是将其处理为@987654345 @VBA 过程内部的数据。
  • 我在一篇文章中提出两个问题的惩罚是我得到了两个绝妙的答案(感谢@Comintern 和@MathieuGuindon)。我将此标记为答案,因为它根据使用情况彻底解释了差异和原因。
  • @ChrisB 公平地说,“彻底的区别”在微软文档的链接后面;我的回答 [故意] 将大部分 实际 答案留给读者,而共产国际的回答更明确地说明了何时使用每个功能以及它们的执行方式:我对投票的数量感到惊讶这个答案得到了..我不介意你给共产国际的答案打勾;-)
【解决方案2】:

TL;DR 除非您有特定的理由为函数使用 Excel 的语义(即复制它将在单元格中给出的结果,否则如果您关心性能,请不要使用 IsNumber .

首先,结果(和性能)会根据传递给函数的数据类型而有所不同。如果您直接从工作表中提取值,您必须意识到 Excel 会根据您访问它的方式以不同的方式转换值:

Public Sub Foo()
    Debug.Print IsNumeric("1e12")   'True
    Debug.Print Application.WorksheetFunction.IsNumber("1e12")  'False
    [A1] = "1e12"
    'The next 2 are the same, but the first is an implicit call to .Value
    Debug.Print Application.WorksheetFunction.IsNumber([A1])    'True 
    Debug.Print Application.WorksheetFunction.IsNumber([A1].Value)    'True
    Debug.Print Application.WorksheetFunction.IsNumber([A1].Text)    'False
End Sub

接下来,针对WorksheetFunction 的解引用调用有少量开销,因此我将在下面的基准测试中通过将其包装在With 块中来控制它。还要注意处理字符串和数字之间的性能差异(和返回值 o_O):

Private Const ITERATIONS As Long = 1000000

Private Sub RunAll()
    Test 1000
    Test "1000"
End Sub

Private Sub Test(testValue As Variant)
    IsNumericBenchMark testValue
    IsNumberBenchMark testValue
End Sub

Private Sub IsNumericBenchMark(inputValue As Variant)
    Dim start As Single, i As Long
    start = Timer
    For i = 1 To ITERATIONS
        IsNumeric inputValue
    Next
    Debug.Print "IsNumeric" & vbTab & Timer - start & vbTab & IsNumeric(inputValue)
End Sub

Private Sub IsNumberBenchMark(inputValue As Variant)
    Dim start As Single, i As Long
    start = Timer
    With WorksheetFunction
        For i = 1 To ITERATIONS
            .IsNumber inputValue
        Next
    End With
    Debug.Print "IsNumber" & vbTab & Timer - start & vbTab & WorksheetFunction.IsNumber(inputValue)
End Sub

结果:

IsNumeric   0.09375     True
IsNumber    5.664063    True
IsNumeric   0.6796875   True
IsNumber    6.796875    False

这是官方的,IsNumber 并不是表现最好的人。

【讨论】:

  • 请解引用是什么意思?我只有一个模糊的概念。
  • . 是 VBA 取消引用运算符。 WorksheetFunctionApplication 对象上的一个接口,它们之间的. 让您从对象中获得对该接口的引用。因此,“取消引用”。通过处理. 正在执行实际工作。 With 块包含一个对象引用,因此它可以防止重复取消引用 Application.WorksheetFunction
  • 优秀的答案!我几乎想将此标记为答案,只是为了教我如何轻松进行基准测试。
  • ITERATIONS 是未声明的常量吗? ;)
  • @FreeMan 复制和粘贴错误,已修复。感谢您的提醒。
猜你喜欢
  • 2017-04-07
  • 2011-03-05
  • 1970-01-01
  • 2023-02-14
  • 2011-04-21
  • 2011-12-20
  • 1970-01-01
相关资源
最近更新 更多