2015-10-18 1 views
1

Я нахожусь в создании пользовательской формы в excel, которая использует несколько ComboBox. Первый ComboBox перечисляет значения из столбца 1 таблицы, а следующие списки ComboBox перечисляют значения из следующих столбцов. ComboBox 2 также содержит только значения, зависящие от предыдущего. Все ComboBox показывают только уникальные значения.Очистить каскадный ComboBox при повторном выборе

Вот текущий код, я использую:

Option Explicit 
Private Sub ComboBox1_Change() 
    Call cValues(ComboBox1.Value, ComboBox2, 2) 
End Sub 
Private Sub ComboBox2_Change() 
    Call cValues(ComboBox2.Value, ComboBox3, 3) 
End Sub 
Private Sub ComboBox3_Change() 
    Call cValues(ComboBox3.Value, ComboBox4, 4) 
End Sub 
Private Sub ComboBox4_Change() 
    Call cValues(ComboBox4.Value, ComboBox5, 5) 
End Sub 
Private Sub ComboBox5_Change() 
    Call cValues(ComboBox5.Value, ComboBox6, 6) 
End Sub 

Private Sub UserForm_Initialize() 
    Dim Rng   As Range 
    Dim Dn   As Range 
    Dim Dic   As Object 
    With Sheets("Listuni") 
     Set Rng = .Range(.Range("A2"), .Range("A" & Rows.Count).End(xlUp)) 
    End With 
    Set Dic = CreateObject("scripting.dictionary") 
    Dic.CompareMode = vbTextCompare 

    For Each Dn In Rng: Dic(Dn.Value) = Empty: Next 
    Me.ComboBox1.List = Application.Transpose(Dic.keys) 
End Sub 

Sub cValues(txt As String, Obj As Object, col As Integer) 
    Dim Dn    As Range 
    Dim Rng    As Range 
    Dim Dic    As Object 
    With Sheets("Listuni") 
     Set Rng = .Range(.Cells(2, col), .Cells(Rows.Count, col).End(xlUp)) 
    End With 
    Set Dic = CreateObject("Scripting.Dictionary") 
    Dic.CompareMode = 1 

    For Each Dn In Rng 
     If Dn.Offset(, -1).Value = txt Then 
      If Not Dic.exists(Dn.Value) Then 
       Dic(Dn.Value) = Empty 
      End If 
     End If 
    Next Dn 
    Obj.List = Application.Transpose(Dic.keys) 
End Sub 

Проблема, которую я имею, когда пользователь делает повторный выбор предыдущего ComboBox. Вместо очистки последующих блоков все существующие выборы остаются.

Я ищу способ очистить/по умолчанию значения последующего ComboBox каждый раз при повторном выборе предыдущего ComboBox. Например, если я сделаю выбор в ComboBox 1 и 2, но затем измените свой выбор на ComboBox 1, я хочу, чтобы ComboBox 2 очистился, а не показывал мой предыдущий выбор. Обратите внимание, что позиция по умолчанию для формы пользователя при запуске не показывает значений в любом ComboBox.

Я попытался с помощью .clear метода на изменения, однако это всегда получает повешен на:

Obj.List = Application.Transpose(Dic.keys) 

Я подозреваю, что это потому, что ясно технически изменения и, следовательно, он не может перенести список значений в другие ящики, основанные на нулевом значении.

ответ

2

Это очищает все последующие ComboBoxes - если Combo1 изменения, Combo2, 3, 4, 5, и 6 очищаются

Option Explicit 

Private ws As Worksheet 
Private d As Object 

Private Sub UserForm_Initialize() 
    Dim cel As Range, txt As String, rng As Range 

    Set ws = Worksheets("Listuni") 
    Set d = CreateObject("Scripting.Dictionary"): d.CompareMode = vbTextCompare 

    Set rng = ws.Range(ws.Cells(2, 1), ws.Cells(ws.Rows.Count, 1).End(xlUp)) 

    For Each cel In rng: d(cel.Value) = Empty: Next 
    ComboBox1.List = Application.Transpose(d.keys) 
End Sub 

Private Function setList(ByVal txt As String, ByRef cmb As ComboBox) As Object 
    Dim xID As Long, rng As Range, cel As Range, x As Control 

    xID = Right(cmb.Name, 1) 
    For Each x In Me.Controls 
     If TypeName(x) = "ComboBox" Then If Val(Right(x.Name, 1)) > xID - 1 Then x.Clear 
    Next 

    Set rng = ws.Range(ws.Cells(2, xID), ws.Cells(ws.Rows.Count, xID).End(xlUp)) 

    d.RemoveAll 
    For Each cel In rng 
     If cel.Offset(, -1) = txt Then 
      If Not d.exists(cel.Value) Then 
       d(cel.Value) = Empty 
      End If 
     End If 
    Next 
    If d.Count > 0 Then cmb.List = Application.Transpose(d.keys) Else cmb.Clear 
End Function 

Private Sub ComboBox1_Change() 
    setList ComboBox1.Value, ComboBox2 
End Sub 
Private Sub ComboBox2_Change() 
    setList ComboBox2.Value, ComboBox3 
End Sub 
Private Sub ComboBox3_Change() 
    setList ComboBox3.Value, ComboBox4 
End Sub 
Private Sub ComboBox4_Change() 
    setList ComboBox4.Value, ComboBox5 
End Sub 
Private Sub ComboBox5_Change() 
    setList ComboBox5.Value, ComboBox6 
End Sub 

cascade

+1

Привет, спасибо за это. Пробовал, и ComboBox 1 перечисляет значения, как ожидалось. После выбора я встречаю ошибку времени выполнения «несоответствие типа». Все данные в таблицах являются текстовыми. – user1993376

+1

Отладка возвращает меня к первому «Следующему» в пределах частной функции setList code – user1993376

+1

Только что проверено, и код не показывает ошибку, однако возникла другая проблема. Если бы я должен был выбрать значение из ComboBox1, тогда ComboBox 2 отображает только первое соответствующее значение из столбца b. В моем случае существует много разных связанных значений из столбцов с 1 по 2. Например, если я выбираю США в первом ComboBox, я хотел бы видеть все различные состояния, соответствующие США в ComboBox 2, поскольку они перечислены в столбце B таблицы. Если я изменю выбор в ComboBox 1 в Великобритании, тогда ComboBox 2 должен перечислить все города в ComboBox 2 в Великобритании и так далее. – user1993376