vba 变体数组错误

Posted

技术标签:

【中文标题】vba 变体数组错误【英文标题】:vba variant array bug 【发布时间】:2012-07-20 15:53:41 【问题描述】:

我对 excel vba 还很陌生,我似乎无法用 vbArrays 解决这个问题。我在 vba 中创建了函数 cumsum 只是为了让我的生活更轻松。但是,我想让代码灵活,这样我就可以从函数和范围中传递两种变体。在我的代码中,当我添加行 vec=vec.value 如果我传入一个范围时,它工作得非常好,但如果我希望它在我调用函数并传入非范围类型时工作,它就不起作用.我注意到的是,如果我的代码中没有 vec=vec.value 行并且我传入一个范围,它的维度为 0,我通过编写自己的函数进行检查。有人可以向我解释如何解决这个问题吗?谢谢。

Public Function cumsum(vec As Variant) As Variant
    Dim temp() As Variant
    MsgBox (getDimension(vec))
    'works if i use vec=vec.value if vec is a range but has 0 if i do not vec = vec.values
    ReDim temp(LBound(vec, 1) To UBound(vec, 1), 1 To 1) As Variant
    Dim intCounter As Integer
    For intCounter = LBound(vec) To UBound(vec)
        If intCounter = LBound(vec) Then
            temp(intCounter, 1) = vec(intCounter, 1)
        Else
            temp(intCounter, 1) = temp(intCounter - 1, 1) + vec(intCounter, 1)
        End If
    Next
    cumsum = temp()
End Function
Function getDimension(var As Variant) As Integer
On Error GoTo Err:
    Dim i As Integer
    Dim tmp As Integer
    i = 0
    Do While True:
        i = i + 1
        tmp = UBound(var, i)
    Loop
Err:
    getDimension = i - 1
End Function

【问题讨论】:

【参考方案1】:

您为什么不使用VarType 和TypeName 来检查vec 的数据类型,然后对vec 执行必要的操作

Public Function cumsum2(vec As Variant) As Variant
    MsgBox TypeName(vec)
    MsgBox VarType(vec)

    cumsum2 = 0
End Function

【讨论】:

我试过了。当您对范围进行 vartype 时,它​​仍然认为它是一个 vbarray 并且对于变体也是如此 使用 TypeName 会发生什么? 您能否更新您的问题以显示您如何将值传递给 cumsum()? 还尝试从 vba dim trial 调用函数作为变体 redim trial(1 到 10) 作为变体 dim i 作为整数 i = 1 到 10 trial(i) = i next cumsum(trial) 请看我更新的答案。您是否像我一样检查类型?【参考方案2】:

@Jake 和@chris 的回答暗示了正确的方向,但我认为它们还远远不够。

如果您绝对确定只会将此例程称为 UDF(即来自工作表中的公式),那么您真正需要做的就是添加以下内容:

If IsObject(vec) Then
    Debug.Assert TypeOf vec Is Range

    vec = vec.Value2
End If

到你的函数的开始。称为 UDF,它应该被传递的唯一对象类型是 Range。此外,称为 UDF,您可以依赖这样一个事实,即它传递的任何数组都将从 1 开始索引。

我可以找出您日常工作中的其他问题,但它们与您最初的问题无关。简而言之:这仅适用于列向量,对于单单元格范围等将失败。

请注意,getDimension 函数为 Ranges 返回零的原因是 UBound 在范围内阻塞。您的错误处理程序很高兴地捕捉到您并不真正期望得到的错误(类型不匹配)并返回零。 (查找“维度”的方法假设错误将是下标超出范围错误。)

我不久前写了一个答案,描述了为什么在使用 Excel 时,我认为一般的 getDimension 方法不是一个好方法:

https://***.com/a/6904433/58845

最后,VarType 的问题在于,当传递一个具有默认属性的对象时,它实际上会返回该属性的类型。所以VarType(<range>) 会告诉你范围内的东西的类型,而不是对象的代码,因为Range 有一个默认属性Range.Value

【讨论】:

【参考方案3】:

修改您的getDimension 以包含

If TypeName(var) = "Range" Then
    var = var.Value
End If

【讨论】:

以上是关于vba 变体数组错误的主要内容,如果未能解决你的问题,请参考以下文章

VBA:只有在公共对象模块中定义的用户定义类型才能被强制转换为变体或从变体强制转换或传递给后期绑定函数

布尔数组和变体类型 vba

变体数组自定义函数谷歌表格?以 VBA 为例

VBA:如何使变体为空?

在 VBA 中添加或相乘变体

尝试调用外部 VBA 函数时,只能强制在公共对象模块中定义的用户定义类型