【问题标题】:Handle Error 9 when there is an Empty Array有空数组时处理错误 9
【发布时间】:2011-05-05 01:33:35
【问题描述】:

我正在编写一个脚本,该脚本将遍历 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


    【解决方案1】:

    试试这个检查一个空数组:

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

    HTH!

    【讨论】:

    • 我声称没有专业知识,但显然这种检查空数组的方法正在利用 VBA 中的一个错误,不应使用:stackoverflow.com/questions/183353/…
    • @jtolle - 您的链接肯定是对这个问题的最终讨论。也许这个 Q 应该标记为 dup。或者至少您的链接应该是 Talguy 问题的答案。
    • @jtolle 可能是。我以前用过这个东西,但由于不是我创造的,所以我不声称它有任何优点。
    【解决方案2】:

    您的函数失败了,因为如果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
    

    【讨论】:

    • 效果更好,但我仍然收到错误 #9 脚本越界
    • Dim a(): Debug.Print IsArrayEmpty(a) 对我来说很好......确保你没有工具>选项>常规>打破所有错误集
    【解决方案3】:

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

    'Empty' 是一个未初始化的变体:IsEmpty(myVar) 将返回 true... 你可能会误以为你有一个空数组(它是 'Empty()',而不是 'Empty' - 尽量保持up,这个类之后会有一个简短的测试)因为 IsEmpty(myArray) 也返回 True。

    Dim myVar as Variant ' 这当前为空,Ubound 返回错误
    Dim myArray() as variant ' 这当前是 Empty(),Ubound 返回错误

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

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

    如果 Instr(Typename(myVar), "(") > 0 那么 ' 我们现在知道它是一个数组 If Not IsEmpty(myVar) Then ' 我们现在可以检查它的尺寸 如果 Ubound(myVar) > 0 ' 在此处插入无错误代码 万一 万一 万一

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

    【讨论】:

      【解决方案4】:

      Chip Pearson 多年前提供了answer,它仍然有效。这是我在图书馆使用了将近四年的函数。

      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
      

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

      【讨论】:

      • 在空字符串Split()之后的结果数组求值中可以看到一个被注释的“奇怪行为”的例子:UBound(Split("","splitter")) = -1,LBound(Split("","splitter")) = 0。也许这只是一种(尴尬的)表示基本字符串函数错误的方式,类似于某些字符串函数传统上在各种语言和平台中返回 -1。
      【解决方案5】:

      .. 我仍然收到错误 #9 脚本 越界

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

      【讨论】:

      • 这是我想要的信息,但它的程序不会跳转到错误处理程序,而是会弹出错误 9
      • 嗨,Talguy,你试过 Alex K. sugestion 吗?根据此链接pcreview.co.uk/forums/thread-3387988.php>,如果您在一个办公程序中更改它,它可以转移到另一个。
      • 查看此链接 cpearson.com/Excel/ErrorHandling.htm>。 “错误处理块和错误转到”部分。 (同一过程中有多个“On Error”语句,不会正确捕获。)
      【解决方案6】:

      你总是可以使用“isArray()”函数

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

      【讨论】:

        【解决方案7】:

        您可以通过使用 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 sec。相同的功能可以通过ScriptControl ActiveX 实现(它在 64 位 MS Office 版本中不可用,因此您可以使用类似this 的解决方法)。

        【讨论】:

          【解决方案8】:

          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  
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-07-29
            • 2015-12-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-08
            • 2015-08-06
            相关资源
            最近更新 更多