【问题标题】:Is there a way to create a VBA function that can take in both arrays and ranges as input?有没有办法创建一个可以同时接受数组和范围作为输入的 VBA 函数?
【发布时间】:2019-12-01 05:28:53
【问题描述】:

我正在尝试创建一个可以同时接受范围或数组的函数来执行一些进一步的计算。当一个数组通过时,该函数工作正常,但是当该函数用于工作表中的范围时,它给了我 VALUE!错误。

我的代码如下:

Function COMRET(data as variant, N as integer)

     Dim nrows as long

     If IsArray(data) Then
        N = UBound(data,1)
     Else
        N = data.rows.count
     End If

     '... some other calculations here

End Function

问题似乎来自上面对数组的识别......当我注释掉上面的 IF 部分时,代码的其他部分似乎没问题。不知道我在这里做错了什么。感谢帮助。谢谢!

【问题讨论】:

    标签: arrays vba function range


    【解决方案1】:

    声明data as Variant是正确的。
    当您向其中传递一个范围时,它将作为 Variant/Object/Range 正确传递,但随后事情会变得有点复杂。

    当你调用IsArray,这是一个纯函数,它会尝试使用传递的Range对象的default property,也就是Value。如果 Range 包含多个单元格,IsArray(Range.Value) 为 True。但是当你再调用UBound,这是一个非常特殊的函数,因为它被高亮显示为关键字,它不会尝试获取data.Value,而是直接对data进行操作,而data是单个@987654331 @ 对象,所以它不能有上限(而它的.Value 可以)。

    您需要正确检测您被传递的内容:

    Public Function COMRET(data As Variant, N As Integer)
        Dim nrows As Long
    
        If TypeOf data Is Range Then
            N = data.Rows.Count
        ElseIf IsArray(data) Then
            N = UBound(data, 1)
        Else
            ' ???
        End If
    
    End Function
    

    【讨论】:

    • 谢谢.. 我想我更喜欢这个解决方案来解决我的问题。
    【解决方案2】:

    您将 data 作为 Variant 传递,这将导致 IsArray(data) 始终显示为真,无论您在调用函数时是否将范围或数组传递给它。

    添加第三个强制参数也可以,指示data变量的数据类型:

    Function COMRET(data As Variant, Is_Array As Boolean, N As Integer)
    
         Dim nrows As Long
    
         If Is_Array = True Then
            N = UBound(data, 1)
         Else
            N = data.Rows.Count
         End If
    
         '... some other calculations here
    
    End Function
    

    或者,您可以添加一个检查,该检查使用尝试在某个范围上使用 UBound 时引发的错误。这清除了第三个参数的需要:

    Function COMRET(data As Variant, N As Integer)
    
        Dim nrows As Long
    
        On Error Resume Next
            N = UBound(data, 1)
            If Err.Number <> 0 Then N = data.Rows.Count
            Err.Clear
        On Error GoTo 0
    
        '... some other calculations here
    
    End Function
    

    【讨论】:

    • 我明白了...感谢您的快速回答。将相应地调整我的代码。
    • 很高兴能帮上忙!
    【解决方案3】:

    VarType() 应该是你的朋友:

    ' Const vbArray = 8192 (&H2000)
    ' Const vbString = 8
    Debug.Print VarType(data)  ' = vbArray (8192) Or vbString (8) = 8200
    
    ' Is data an array of sorts?
    Debug.Print CBool((VarType(data) And vbArray) = vbArray)
    

    来自 MSDN 帮助:

    VarType 函数永远不会单独返回 vbArray 的值。它 总是添加到某个其他值以指示一个数组 特定类型。常量 vbVariant 仅在 与 vbArray 一起表示 VarType 的参数 function 是 Variant 类型的数组。例如返回的值 对于整数数组,计算为 vbInteger + vbArray,或 8194.如果对象有默认属性,VarType(object)返回对象默认属性的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-30
      • 2021-07-04
      • 2016-10-12
      • 2020-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多