MSForms.ListBox VBA 如何自定义多选?
How to costumize MultiSelect for MSForms.ListBox VBA?
嗨,我想实现以下目标:
我有一个带有列表框的用户窗体。此列表框应具有以下选择行为:
这是我的列表框:
1 鼠标点击切换选择
2 在按住鼠标按钮单击的同时移动到项目上将切换选择
遗憾的是,此行为与 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
So what I tried was the following: When the Selection gets changed it will compare if that element was selected before and will keep it.这不会稍微改变 MultiSelect 的行为。我认为至少应该保留所有已选择一次的项目。
编辑:添加了一些图片和代码作为我尝试过的示例,以及它应该如何运行。
好的,我明白了:
首先,您从 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
属性,它告诉您“光标”在列表中的位置。这也是按住鼠标时鼠标所在的位置。所以你所要做的就是:
如果一个列表项的值发生变化,并且列表索引不等于更改项的索引,则将该项切换回初始状态。
先决条件
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
您需要在同一个用户表单中满足先决条件才能正常工作。我认为 UpdateSelectedCol
和 toggleitem
很容易重构。
嗨,我想实现以下目标:
我有一个带有列表框的用户窗体。此列表框应具有以下选择行为:
这是我的列表框:
1 鼠标点击切换选择
2 在按住鼠标按钮单击的同时移动到项目上将切换选择
遗憾的是,此行为与 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
So what I tried was the following: When the Selection gets changed it will compare if that element was selected before and will keep it.这不会稍微改变 MultiSelect 的行为。我认为至少应该保留所有已选择一次的项目。
编辑:添加了一些图片和代码作为我尝试过的示例,以及它应该如何运行。
好的,我明白了:
首先,您从 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
属性,它告诉您“光标”在列表中的位置。这也是按住鼠标时鼠标所在的位置。所以你所要做的就是:
如果一个列表项的值发生变化,并且列表索引不等于更改项的索引,则将该项切换回初始状态。
先决条件
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
您需要在同一个用户表单中满足先决条件才能正常工作。我认为 UpdateSelectedCol
和 toggleitem
很容易重构。