VBA中的WorksheetFunction.IsNumber()和IsNumeric()有什么区别?

时间:2018-07-27 02:02:03

标签: vba excel-vba function

在VBA中使用这两个功能有何区别?使用一个相对于另一个有速度优势吗?

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

2 个答案:

答案 0 :(得分:9)

IsNumeric是位于VBA.Information模块中的VBA标准库函数,例如IsArrayIsDateIsErrorErr,{ {1}}等:

VBE Object Browser showing IsNumeric in the VBA standard library

作为VBA标准库的一部分,它可以在不依赖主机应用程序的情况下工作:该标准库可以安全地假定为运行VBA的计算机上的现有库。

另一方面,可以在Microsoft Excel对象模型库中找到

Application.WorksheetFunction.IsNumber

VBE Object Browser showing IsNumber in the Excel type library

因此,该代码仅在引用Excel类型库的情况下才有效。如果您已经在Excel中,那不是问题。但是,如果您使用的是Word,并且希望使用一个在给定的VarType为数字时返回Boolean的函数,则您不想为此引用整个Excel类型库。

String接口是Excel计算引擎的网关:有了它,您就可以编写VBA代码,现在可以对经过精心设计的普通VBA数组使用INDEX / MATCH了-太棒了。但是,不能保证Excel的计算引擎的工作方式与VBA完全相同。如果要遵守Excel的规则,请使用WorksheetFunction

尽管如此,我可能会假设WorksheetFunctionVBA.Information.IsNumeric快:我可能是错的,但是似乎仅VBA标准库涉及的运动部件就更少。

但找出答案的唯一方法:

  

您有两匹马-赛跑!

;-)

答案 1 :(得分: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

接下来,对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并非表现最佳。