访问集合会导致下标超出范围错误?

时间:2019-03-14 20:09:58

标签: excel vba exception runtime-error

我有一个UserForm,如果用户输入不正确,则会调用以下过程,该过程将突出显示该字段并禁用“保存更改”按钮。

Private disabledElems As New Collection

Private Sub disable(ByRef controlName As String)
    UserForm1.Controls(controlName).BackColor = &H8080FF
    Me.save_button.Enabled = False
    Dim i As Byte

    If disabledElems.Count <> 0 Then
        For i = 1 To disabledElems.Count
            If disabledElems(i) = controlName Then
                Exit Sub ' we dont want to add duplicates to collection
            End If
        Next i
    End If

    disabledElems.Add controlName ' otherwise add to collection

End Sub

如果输入正确,它将调用enable过程,如下所示:

Private Sub enable(ByRef controlName As String)
    Me.Controls(controlName).BackColor = &H80000005
    Dim i As Byte

    For i = 1 To disabledElems.Count
        If disabledElems(i) = controlName Then
            disabledElems.Remove i ' remove the enabled element upon match 
        End If
    Next i

    If disabledElems.Count = 0 Then
        save_button.Enabled = True
    End If


End Sub
  

当我尝试使用一个Textbox

时,这似乎很好用      

enter image description here


但是,一旦我有多个不正确的条目,我的enable过程似乎就毫无理由地抛出了 Subscript out of range error

调试器中突出显示的行是:

If disabledElems(i) = controlName Then

enter image description here

我不明白是什么原因造成的。有什么想法吗?

enter image description here

1 个答案:

答案 0 :(得分:1)

  

好的,这是那些经典的”之一,当删除一行时,循环   从头到尾”

基本上,抛出 Subscript out of range 的原因-一旦通过

从集合中删除了元素
disabledElems.Remove i

Collection的大小从Collection.Count减小到Collection.Count - 1,但是在for循环声明期间,i已经很困难了-设置到前一个Collection.Count


  

在一个实际示例中:

假设我的Collection看起来像这样

 disabledElems = "button1", "button2"

执行此操作

controlName = "button1"
For i = 1 to disabledElems.Count ' <= 2
   If disabledElems(i) = controlName ' < True for i = 1
      disabledElems.Remove i ' < button1 was removed from collection, however it still loops
   End If
   ' will loop to i = 2. However disabledElems(2) no longer exists, because upon removal _
     the button2 was shifted to disabledElems(1) - hence Subscript out of range
Next i

一个试图访问元素的明确案例,该元素在队列中的位置已经改变。


有两种可能的修复方法(我能想到)

1。删除后强制执行Exit Sub

For i = 1 to disabledElems.Count
   If disabledElems(i) = controlName
       disabledElems.Remove i
       Exit Sub
   End If
Next i

2。从头到尾循环

Dim i as Integer ' needs to be redeclared to int, because Byte can't -1
For i = disabledElems.Count to 1 Step -1
   If disabledElems(i) = controlName
      disabledElems.Remove i
   End If
Next i