有没有一种方法可以创建可以将数组和范围都作为输入的VBA函数?

时间:2019-07-23 08:09:22

标签: arrays vba function range

我正在尝试创建一个可以接受范围或数组的函数来执行一些进一步的计算。当数组通过时,该函数运行良好,但是当在工作表中的范围内使用该函数时,它的值为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部分时,代码的其他部分似乎还可以。不知道我在做什么错。感谢帮助。谢谢!

3 个答案:

答案 0 :(得分:1)

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

添加第三个强制性参数也可以,它指示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

答案 1 :(得分:1)

您正确声明data as Variant
当您将范围传递给该范围时,它将正确地作为Variant / Object / Range传递,但是事情会变得有些复杂。

当您调用仅作为函数的IsArray时,它将尝试使用传递的Range对象Value的{​​{3}}。如果范围由多个单元格组成,则IsArray(Range.Value)为True。但是,当您调用UBound时,这是一个非常特殊的功能,因为它被突出显示为关键字,它不会尝试获取data.Value并将直接在data上进行操作,而{{ 1}}是单个data对象,因此它不能有上限(而Range可以)。

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

.Value

答案 2 :(得分:0)

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的参数   函数是Variant类型的数组。例如,返回的值   对于整数数组的计算方式为vbInteger + vbArray,或者   8194.如果对象具有默认属性,则VarType(对象)将返回该对象的默认属性的类型。