什么是VBA中的WorksheetFunction.IsNumber()和IsNumeric()之间的区别?

Chr*_*isB 3 vba function excel-vba

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

Application.WorksheetFunction.IsNumber(myVar)
IsNumeric(myVar)
Run Code Online (Sandbox Code Playgroud)

Mat*_*don 9

IsNumeric是位于在VBA标准库函数VBA.Information模块,如IsArray,IsDate,IsError,Err,VarType,和更:

VBE对象浏览器在VBA标准库中显示IsNumeric

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

Application.WorksheetFunction.IsNumber另一方面,可以在Microsoft Excel对象模型库中找到:

VBE对象浏览器在Excel类型库中显示IsNumber

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

WorksheetFunction接口是Excel计算引擎的入口:使用它,您可以编写VBA代码,现在可以使用INDEX/MATCH来对付精心设计的普通VBA阵列 - 它非常棒.但是不能保证Excel的计算引擎与VBA完全相同.如果您想遵循Excel的规则,请使用WorksheetFunction.

我可能会认为VBA.Information.IsNumeric速度要快Excel.WorksheetFunction.IsNumber:我可能错了,但似乎只有VBA标准库涉及的移动部件更少.

但唯一的方法是找出:

你有两匹马 - 比赛他们!

;-)

  • 那是因为"999"不是数字 - 它是一个字符串.当IsNumeric检查是否可以转换时,IsNumber会检查变量的类型.https://msdn.microsoft.com/en-us/vba/excel-vba/articles/worksheetfunction-isnumber-method-excel`不转换IS函数的值参数.例如,在需要数字的大多数其他函数中,文本值"19"被转换为数字19.但是,在公式ISNUMBER("19")中,"19"不从文本值转换,并且ISNUMBER函数返回FALSE (3认同)
  • @JerryJeremiah 需要注意的是,这取决于您是使用 `.Value`(将其转换为 `Variant`)从单元格中提取数据还是将其作为 VBA 程序内部的 `String` 数据处理. (2认同)

Com*_*ern 6

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
Run Code Online (Sandbox Code Playgroud)

接下来,解除引用调用的开销很小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
Run Code Online (Sandbox Code Playgroud)

结果:

IsNumeric   0.09375     True
IsNumber    5.664063    True
IsNumeric   0.6796875   True
IsNumber    6.796875    False
Run Code Online (Sandbox Code Playgroud)

这是官方的,IsNumber并不是最佳表现者.