如何为MSForms.ListBox VBA汇总MultiSelect?

时间:2018-10-16 14:22:12

标签: excel vba excel-vba listbox userform

嗨,我想实现以下目标:

我有一个带有列表框的UserForm。此列表框应具有以下选择行为:

这是我的列表框:

enter image description here

1 MouseClick切换选择

enter image description here

2在按住鼠标按钮的同时将项目移到上方将切换选择

enter image description here

不幸的是,此行为与3个可选的MultiSelect属性不匹配。

0- fmMultiSelectSingle

  • 无法多选

1-fmMultiSelectMulti

非常接近,但:

  • 在按住按钮的同时鼠标不再位于列表项上方时,将取消选择ListItems。

2-fmMultiSelectExtended

也很近,但是:

  • 在选中项目后单击其他位置时,所有项目都将取消选择

总而言之,目标是通过单击鼠标或在单击鼠标时将其移到上方来手动切换所有项目

我试图通过ListBox_Change事件来做到这一点,但我不知道如何。

这是我尝试的代码:

一般的用户窗体:

Private Type TView
    SelectedCol As Collection
    EventsDisabled As Boolean
End Type

Private this As TView

Public Property Get SelectedCol() As Collection
    Set SelectedCol = this.SelectedCol
End Property
Public Property Set SelectedCol(ByVal value As Collection)
    Set this.SelectedCol = value
    'Validate
End Property

Private Sub UserForm_Initialize()
Set SelectedCol = New Collection
counter = 0
Dim i As Integer

For i = 1 To OptionList.ListCount
    SelectedCol.Add Me.OptionList.Selected(i)
Next i
End Sub

UpdateSelectedCol子:

Sub UpdateSelectedCol()
Dim i As Integer
Dim bo As Boolean
For i = OptionList.ListCount To 1
    SelectedCol.Remove (i)
Next i
For i = 1 To OptionList.ListCount
    SelectedCol.Add OptionList.Selected(i - 1)
Next i

End Sub

ListBox_Change事件:

Private Sub OptionList_Change()
Dim i As Integer
If this.EventsDisabled = False Then
    this.EventsDisabled = True
    GO_btn.Enabled = ISSelected(Me.OptionList)

    ' keep selected until changed
    For i = 1 To Me.OptionList.ListCount
        If SelectedCol.Item(i) Then
            Me.OptionList.Selected(i) = True
        End If
    Next i

    Debug.Print SelectedCount(Me.OptionList)
    UpdateSelectedCol
End If
this.EventsDisabled = False
End Sub

所以我尝试了以下操作:当选择更改时,它将比较之前是否选择了该元素并将保留它。这不会稍微改变MultiSelect行为。在我看来,它至少应保留已选择一次的所有项目。

编辑:添加了一些图片和代码作为示例,我尝试了什么,以及它应该如何工作。

1 个答案:

答案 0 :(得分:0)

好吧,我知道了:

首先,从1-MultiSelectMulti作为ListBox属性开始。比将以下代码添加到您的用户表单中:

解决方案

Private Sub OptionList_Change()
Dim i As Integer
If Not this.EventsDisabled Then
    this.EventsDisabled = True
    GO_btn.Enabled = ISSelected(Me.OptionList)

    ' MAIN SOLUTION ************************************************

    ' if has changed keep odl value when not = to listindex
    For i = 1 To Me.OptionList.ListCount
        If Me.OptionList.Selected(i - 1) <> SelectedCol.Item(i) And Not i - 1 = Me.OptionList.ListIndex Then
            ToggleItem (i)
        End If

    ' MAIN SOLUTION END ************************************************

    UpdateSelectedCol
    this.EventsDisabled = False
End If
End Sub

一个很好的线索是.ListIndex属性,它告诉您“游标”在列表中的位置。按住鼠标时,鼠标也将位于该位置。因此,所有要做的就是:

如果一个列表项的值已更改,并且listindex不等于更改项的索引,则将其切换回初始状态。

先决条件

Private Type TView
    SelectedCol As Collection
    EventsDisabled As Boolean
End Type

Private this As TView

Public Property Get SelectedCol() As Collection
    Set SelectedCol = this.SelectedCol
End Property
Public Property Set SelectedCol(ByVal value As Collection)
    Set this.SelectedCol = value
    'Validate
End Property

Private Sub UserForm_Initialize()
Set SelectedCol = New Collection
counter = 0
Dim i As Integer

For i = 1 To OptionList.ListCount
    SelectedCol.Add Me.OptionList.Selected(i - 1)
Next i

End Sub


Sub ToggleItem(i As Integer)
    Me.OptionList.Selected(i - 1) = Not Me.OptionList.Selected(i - 1)
End Sub

Sub UpdateSelectedCol()
this.EventsDisabled = True
Dim i As Integer
Dim bo As Boolean
For i = OptionList.ListCount To 1 Step -1
    SelectedCol.Remove (i)
Next i
For i = 1 To OptionList.ListCount
    SelectedCol.Add OptionList.Selected(i - 1)
Next i
this.EventsDisabled = False
End Sub

您需要使用相同的用户表单中的先决条件才能使其正常工作。我认为UpdateSelectedColtoggleitem很容易重构。