填充ComboBox.List的值时出错

时间:2017-12-11 22:08:43

标签: arrays vba excel-vba excel

我尝试仅使用 UNIQUE 值填充组合框,没有重复项;我相信它工作得很好,但在第二个For循环

中我的逻辑出了问题

以下逻辑如下......

Private Function PopulateComboBoxWeeks()

   Dim i As Long
   Dim x As Long
   Dim LR As Long
   Dim ws As Worksheet
   Dim SearchNextWeek As String

   LR = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
   Set ws = ActiveSheet

   With UserForm1.ComboBox1

      ''' Fill first slot in ComboBox1 with the value of last row in Column "A"
      .AddItem ws.Range("A" & LR).Value

      ''' Loop to search Column "A" for items to fill with, start on the second last row, since the above line fills the first line
      For i = LR - 1 To 2 Step -1

         ''' Loop to search the ComboBox.List() array
         For x = 0 To .ListCount
            ''' Array list starts at 0
            If Not (.List(x) = ws.Range("A" & i).Value) Then
               .AddItem ws.Range("A" & i).Value
            End If

         Next x

      Next i

   End With

End Function

它正确地检查了数组列表,但是如果我从数组的索引For开始,我就停留在第二个0循环上了考虑到.ListCount数组中的项目总数。因此,它给了我以下错误......

  

运行时错误' 381'

     

无法获取List属性。无效的属性数组索引

这可能只意味着我引用了数组大小之外的数组项。我尝试过.ListCount - 1,但这给了我一个无限循环。我认为我的所有逻辑都是合理的,除了这一项,我不知道如何通过这一点。

1 个答案:

答案 0 :(得分:1)

在你改变它时迭代任何集合总是一个坏主意。

不要循环任何东西。只需告诉它你想要使用的范围。

如果你不能这样做,那么你需要首先将唯一值放入数组(单维),然后分配ComboBox1.List = theArray。完成。

您想要做两件事:

  1. 弄清楚唯一值是什么
  2. 分配List属性
  3. 不要在一个嵌套的意大利面条循环中做这两件事。将它们分开。

    Dim allValues As Variant
    'get a single-dimensional array with all the values in the column:
    allValues = Application.WorksheetFunction.Transpose(ws.Range("A2:A" & LR).Value)
    
    'let's use built-in collection keys to ensure uniqueness:
    Dim uniqueValuesColl As Collection
    Set uniqueValuesColl = New Collection
    
    Dim currentIndex As Long
    For currentIndex = LBound(allValues) To UBound(allValues)
        If Not IsError(allValues(currentIndex)) Then
            On Error Resume Next
            uniqueValuesColl.Add allValues(currentIndex), Key:=CStr(allValues(currentIndex))
            If Err.Number <> 0 Then
                ' we already have that value
                Err.Clear
            End If
            On Error GoTo 0
        End If
    Next
    
    'now we know what the unique values are - get them into an array:
    ReDim uniqueValues(0 To uniqueValuesColl.Count - 1)
    Dim currentItem As Variant
    currentIndex = 0
    For Each currentItem In uniqueValuesColl
        uniqueValues(currentIndex) = currentItem
        currentIndex = currentIndex + 1
    Next
    
    'just assign the list of unique values
    ComboBox1.List = uniqueValues
    

    所以我迭代所有值一次,然后迭代一次唯一值。但是,您目前正在为非唯一列表中的每个项目迭代它们一次。所以这个解决方案是 O(n + m),其中 n 是非唯一项目的数量, m 是唯一项目的数量,而你的嵌套循环是 O(n 2 (你的解决方案的大O符号实际上比这更复杂,但我不是大O专家)