存在空数组时处理错误 9

问题描述 投票:0回答:9

我正在编写一个脚本,它将循环遍历 Excel 电子表格并查找所选单元格是否有重复项。如果存在重复项,则该函数将返回一个数组,其中的行是重复的,并创建一条注释来告诉我这些行。

我已经能够处理错误 0,但现在当我使用 UBound 函数检查数组中是否有元素时,出现错误 9。

如何验证整数数组是否为空?

Function IsArrayEmpty(anArray As Variant) As Boolean
    Dim i As Integer

    On Error Resume Next
        i = UBound(anArray, 1)
    Select Case (Err.Number)
        Case 0
            IsArrayEmpty = True
        Case 9
            IsArrayEmpty = True
        Case Else
            IsArrayEmpty = False
    End Select
End Function
excel vba error-handling excel-2003
9个回答
8
投票

尝试检查空数组:

Dim arr() As String

If (Not arr) = -1 Then
   Debug.Print "empty"
Else
   Debug.Print "UBound is " & UBound(X)
End If  

哈!


7
投票

您的函数失败,因为如果

UBound()
没有引发错误(即数组已确定尺寸),则
Err.Number
为 0 并且:

Case 0
  IsArrayEmpty = True

执行后返回错误结果。

最简单的方法就是捕获错误:

Function IsArrayEmpty(anArray As Variant) As Boolean
On Error GoTo IS_EMPTY
If (UBound(anArray) >= 0) Then Exit Function
IS_EMPTY:
    IsArrayEmpty = True
End Function

4
投票

你的数组变体是Empty还是Empty()?

'Empty' 是一个未初始化的变体:IsEmpty(myVar) 将返回 true...并且您可能会被愚弄,认为您有一个空数组(这是 'Empty()',而不是 'Empty' - 尝试跟上,在这堂课之后将会有一个简短的测试)因为 IsEmpty(myArray) 也返回 True。

Dim myVar as Variant '当前为空,Ubound 返回错误
Dim myArray() asvariant ' this is current Empty(), and Ubound returns an error

Redim myVar(0 to 0) '这不再是空的,并且有一个有效的 Ubound
Redim myArray(0 to 0) ' 这不再是空的,并且有一个有效的 Ubound

检查 myVar 的可靠方法是 TypeName(myVar) - 如果它是数组,则名称包含括号:

如果 Instr(Typename(myVar), "(") > 0 那么

    '我们现在知道它是一个数组
    如果不是 IsEmpty(myVar) 那么

       '我们现在可以检查它的尺寸
        如果 Ubound(myVar) > 0
             ' 在此插入无错误的代码
        万一

    万一

万一

完整答案是 Excellerando 上的“检测 Excel VBA 中的数组变体”。


3
投票

Chip Pearson 几年前就给出了答案,现在仍然有效。这是我的图书馆已经使用了近四年的功能。

Public Function IsArrayEmpty(arr As Variant) As Boolean
    Dim lb As Long
    Dim ub As Long

    Err.Clear
    On Error Resume Next

    If IsArray(arr) = False Then
        ' we weren't passed an array, return True
        IsArrayEmpty = True
    End If

    ' Attempt to get the UBound of the array. If the array is
    ' unallocated, an error will occur.
    ub = UBound(arr, 1)
    If (Err.Number <> 0) Then
        IsArrayEmpty = True
    Else
        ''''''''''''''''''''''''''''''''''''''''''
        ' On rare occasion, under circumstances I
        ' cannot reliably replicate, Err.Number
        ' will be 0 for an unallocated, empty array.
        ' On these occasions, LBound is 0 and
        ' UBound is -1.
        ' To accommodate the weird behavior, test to
        ' see if LB > UB. If so, the array is not
        ' allocated.
        ''''''''''''''''''''''''''''''''''''''''''
        Err.Clear
        lb = LBound(arr)
        If lb > ub Then
            IsArrayEmpty = True
        Else
            IsArrayEmpty = False
        End If
    End If

    Err.Clear
End Function

基本上,它检查以确保您传递了一个数组,然后尝试查找上限(如果数组为空,则会抛出错误),最后将下限与上限进行比较以确保数组确实不空。


1
投票

..我仍然收到错误 #9 脚本 超出范围

如果您收到错误#9...这是否意味着您正在获取所需的信息(数组为空)?


1
投票

您始终可以使用“isArray()”函数

Dim yourArray as variant
if not isArray(your_array) then
   msgbox("empty")
else
   msgbox("with data")
end if

0
投票

您可以通过使用 JScript 的

VBArray()
对象检索总元素计数来检查数组是否为空(适用于变体类型、单维或多维数组):

Sub Test()

    Dim a() As Variant
    Dim b As Variant
    Dim c As Long

    ' Uninitialized array of variant
    ' MsgBox UBound(a) ' gives 'Subscript out of range' error
    MsgBox GetElementsCount(a) ' 0

    ' Variant containing an empty array
    b = Array()
    MsgBox GetElementsCount(b) ' 0

    ' Any other types, eg Long or not Variant type arrays
    MsgBox GetElementsCount(c) ' -1

End Sub

Function GetElementsCount(aSample) As Long

    Static oHtmlfile As Object ' instantiate once

    If oHtmlfile Is Nothing Then
        Set oHtmlfile = CreateObject("htmlfile")
        oHtmlfile.parentWindow.execScript ("function arrlength(arr) {try {return (new VBArray(arr)).toArray().length} catch(e) {return -1}}"), "jscript"
    End If
    GetElementsCount = oHtmlfile.parentWindow.arrlength(aSample)

End Function

对我来说,每个元素大约需要 0.3 mksec + 15 msec 初始化,因此 10M 元素的数组大约需要 3 秒。可以通过

ScriptControl
ActiveX 实现相同的功能(它在 64 位 MS Office 版本中不可用,因此您可以使用像 this 这样的解决方法)。


0
投票

UBound 和 LBound 将返回给定数组的上下边界。因此,如果 Ubound(arr) 等于 LBound(arr),则它为空。

Dim arr() As String

If UBound(arr) = LBound(arr) Or UBound(arr) <= 0 Then
   Debug.Print "empty"
Else
   Debug.Print "not empty"
End If  

0
投票

在 MS Excel(Office 365 64 位)中编写 VBA 宏时,我遇到了这个“下标超出范围”问题...

VarType()
调用之前添加对
UBound()
的调用解决了这个奇怪的问题:

Dim arr() As String    ' Empty array - UBound() should return -1 but throws error 9 instead
Dim VT As VbVarType: VT = VarType(arr)
Dim upper_bound: upper_bound = UBound(arr)
© www.soinside.com 2019 - 2024. All rights reserved.