【问题标题】:Is there a range version of IsNumeric just like VBA function HasFormula?是否有像 VBA 函数 HasFormula 一样的 IsNumeric 范围版本?
【发布时间】:2017-04-23 11:08:55
【问题描述】:

我知道 range().HasFormulareturn 仅当范围内的每个单元格都有公式时才返回 True,否则它可以返回 False 或 Null(混合时)。但是没有像 HasNumber 这样的函数。所以要检查一个范围是否只包含数字,我必须这样做

Dim all_numeric As Boolean
all_numeric = True
For Each cell In Range()
    If (Not IsNumeric(cell)) Or IsEmpty(cell) Then 'I also want to get rid of empty cell
        all_numeric = False
        Exit For
    End If
Next cell

此外,WorksheetFunction.IsNumber 做了类似的事情,但仍需要循环遍历范围。 如果范围包含大量数字,我不确定这是否会非常慢。我想知道是否有更好的方法来检查 VBA 中范围对象的数值。

【问题讨论】:

  • 可能是all_numeric = (r.Cells.Count - Application.Count(r)) = 0(其中rRange 对象)?
  • @YowE3K 嗯,漂亮!
  • 这将是 Code Review 最擅长的。我实际上会包含函数的签名/整个主体;如果它只是更大程序的一部分,我会包括整个程序。如果该过程使用模块级变量,我将只包含整个模块。

标签: vba excel


【解决方案1】:

也许all_numeric = (r.Cells.Count - Application.Count(r)) = 0(其中rRange 对象)? – YowE3K35 mins ago

确实是beautiful:它利用 Excel 自己的函数返回范围内数值的数量来确定结果:

WorksheetFunction.Count

计算包含数字的单元格的数量并计算参数列表中的数字。

https://msdn.microsoft.com/en-us/library/office/ff840324.aspx

不计算错误单元格和空单元格,满足您不计算空单元格的要求。

这是一个很好的 UDF,可以在我发现的标准模块中公开:

'@Description("Returns True if all cells in specified range have a numeric value.")
Public Function IsAllNumeric(ByVal target As Range) As Boolean
    IsAllNumeric = target.Cells.Count - Application.WorksheetFunction.Count(target) = 0
End Function

请注意,我使用的是Application.WorksheetFunction.Count,而不是Application.Count

  • 后者是一个后期绑定调用,它使 VBA 运行时工作比它需要的工作更加困难,以找到 Count 方法。您正在处理扩展的 COM 接口,因此您也没有编译时验证:Application.IDontExist 编译得非常好,并因运行时错误 438 而爆炸。与任何其他后期绑定的成员调用,VBE 的 IntelliSense 无法为您提供参数:

  • 前者是一个早期绑定函数调用,VBA在编译时解析。您正在直接处理 WorksheetFunction 接口,因此 VBE 为您提供 autocompleteIntelliSense 参数。

    自动完成:

    智能感知:

调用是早期绑定的这一事实意味着没有运行时开销,因此性能更好——即使它最终与执行的内部 Excel 函数完全相同。

缺点(如果有的话)是后期绑定的Application.SomeFunction 与 Excel4Macros 兼容,这是旧的 VBA 前自动化 Excel 的旧方法。因此,不是引发运行时错误,就像它们的早期绑定对应物一样,后期绑定函数 return 错误 values 这样你 可以 应该IsError测试它们,然后你才能假设你实际得到的是什么类型。

使用提前绑定的WorksheetFunction.SomeFunction 调用,如果 Excel 将显示的结果是 #REF!#VALUE!,或 #N/A 或任何其他可能的错误值,那么您将永远不会被 type mismatch 将错误值视为StringLong 或任何其他非错误VBA 类型的运行时错误。相反,您只需处理运行时错误,就像处理任何其他 VBA API 函数调用一样。

后期绑定调用将错误值传播到您的代码中;早期绑定调用提前失败:在读取单元格值的位置和以假定没有错误值的方式使用该值的位置之间可能有 20 行代码,并且 指令 会引发类型不匹配 - 然后您需要调试以追溯到返回 错误的函数。使用早期绑定代码,函数本身会抛出错误,因此您不必挖掘它。

【讨论】:

  • @这是一个合格的答案,谢谢。两个琐碎的问题,1.Application.WorksheetFunction.CountWorksheetFunction.Count一样吗? 2.你用的是IsAllNumeric(ByVal target As Range)而不是IsAllNumeric(target As Range)(默认参考版),这只是个人习惯吗?
  • 是的,WorksheetFunction.CountApplication.WorksheetFunction.Count 相同 ...我只是喜欢过度限定的东西 ;-) 至于 ByVal,我对 VBA/VB6 的默认设置有点怨恨ByRef(VB.NET 修复了该问题)。如果指针不需要被函数修改,那么函数不应该被赋予这种能力。事故发生得太快了!是的,有一点“复制指针”的开销。但如果是你的性能瓶颈,那么你已经过度优化了。
猜你喜欢
  • 2019-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 2014-04-07
  • 2012-03-31
  • 1970-01-01
相关资源
最近更新 更多