Excel 基于另一个中的选择从后续下拉列表中删除选项
我的VBA表格中有三个下拉列表(cbo_fac1,cbo_fac2,cbo_fac3),每个下拉列表都从同一来源提取数据。但是我想在选择列表组上实现一个级联更新,这样当用户从一个选择列表中选择一个选项时,它就会从后续的选择列表中删除 例如,如果cbo_fac1具有以下选项:Excel 基于另一个中的选择从后续下拉列表中删除选项,excel,vba,Excel,Vba,我的VBA表格中有三个下拉列表(cbo_fac1,cbo_fac2,cbo_fac3),每个下拉列表都从同一来源提取数据。但是我想在选择列表组上实现一个级联更新,这样当用户从一个选择列表中选择一个选项时,它就会从后续的选择列表中删除 例如,如果cbo_fac1具有以下选项: Blu-ray DVD Player Chalk board Computer Data projector Data projector trolley 并且用户从cbo_fac1中选择蓝光DVD播放机,然后接下来的两
Blu-ray DVD Player
Chalk board
Computer
Data projector
Data projector trolley
并且用户从cbo_fac1中选择蓝光DVD播放机
,然后接下来的两个下拉菜单(cbo_fac2和cbo_fac3)应该只有以下选项可用:
Chalk board
Computer
Data projector
Data projector trolley
如果用户随后决定从cbo_fac2中选择数据投影仪台车
,则下一个和最后一个下拉(cbo_fac3)应该只有以下选项可供选择:
Chalk board
Computer
Data projector
当然,如果用户决定返回并更改他们的选项,那么这也应该反映出来。我将如何实现这一目标。这是我目前掌握的代码:
For Each c_fac In ws_misc.Range("fac")
With Me.cbo_fac1
.AddItem c_fac.Value
.List(.ListCount - 1, 1) = c_fac.Offset(0, 1).Value
End With
With Me.cbo_fac2
.AddItem c_fac.Value
.List(.ListCount - 1, 1) = c_fac.Offset(0, 1).Value
End With
With Me.cbo_fac3
.AddItem c_fac.Value
.List(.ListCount - 1, 1) = c_fac.Offset(0, 1).Value
End With
Next c_fac
提前谢谢 这花费的时间比我想象的要长。我以为会更容易:) 对于此解决方案,我将在VBA中使用用户定义的类型。请参见此示例: 将其放在一个模块中:
Option Explicit
Public Type listOptions
name As String
isUsed As Boolean
End Type
在userform上添加三个组合框。将组合框更改为名称:cbo_fac1、cbo_fac2、cbo_fac3
然后在userform后面添加以下代码:
Option Explicit
' options needs to be persisted throughout the life of the program
Dim options() As listOptions
Private Sub UserForm_Initialize()
' setup options
Call getOptionsFromWorksheet("Sheet1")
fillComboBoxWithOptions "cbo_fac1"
fillComboBoxWithOptions "cbo_fac2"
fillComboBoxWithOptions "cbo_fac3"
End Sub
Private Sub getOptionsFromWorksheet(ByRef wsName As String)
Dim ws As Excel.Worksheet
Set ws = ThisWorkbook.Worksheets(wsName)
' assuming data begins at A1
Dim lastCell As Long
Dim i As Long
lastCell = ws.Cells.SpecialCells(xlCellTypeLastCell).Row
ReDim options(lastCell - 1)
For i = 1 To lastCell
options(i - 1) = createOption(ws.Cells(i, 1).Value)
Next
End Sub
Private Function createOption(ByRef theName) As listOptions
Dim opt As listOptions
opt.name = theName
opt.isUsed = False
createOption = opt
End Function
Private Sub cbo_fac1_AfterUpdate()
Call resetSelectedOptions
' reset other combo boxes with options
fillComboBoxWithOptions "cbo_fac2"
fillComboBoxWithOptions "cbo_fac3"
End Sub
Private Sub cbo_fac2_AfterUpdate()
Call resetSelectedOptions
' reset other combo boxes with options
fillComboBoxWithOptions "cbo_fac1"
fillComboBoxWithOptions "cbo_fac3"
End Sub
Private Sub cbo_fac3_AfterUpdate()
Call resetSelectedOptions
' reset other combo boxes with options
fillComboBoxWithOptions "cbo_fac1"
fillComboBoxWithOptions "cbo_fac2"
End Sub
' Resets the combobox control with the available options
Private Sub fillComboBoxWithOptions(ByRef comboBoxName)
Dim selectedItem As String
' get and store the selected item, if any,
' so we can re-select it after we clear it out and re-fill it
If (Me.Controls(comboBoxName).ListIndex <> -1) Then
selectedItem = Me.Controls(comboBoxName).List(Me.Controls(comboBoxName).ListIndex)
End If
Me.Controls(comboBoxName).Clear
Dim i As Long
For i = 0 To UBound(options)
If (options(i).name = selectedItem) Then
Me.Controls(comboBoxName).AddItem options(i).name
ElseIf (Not options(i).isUsed) Then
Me.Controls(comboBoxName).AddItem options(i).name
End If
Next
' re-select the item
For i = 0 To Me.Controls(comboBoxName).ListCount - 1
If (Me.Controls(comboBoxName).List(i) = selectedItem) Then
Me.Controls(comboBoxName).ListIndex = i
Exit For
End If
Next
End Sub
Private Sub resetSelectedOptions()
Dim i As Long
For i = 0 To UBound(options)
options(i).isUsed = False
Next
' Since the list index will not match the index of the options() array
' we have to loop through until we find a matching name and set
' the isUsed = True
If (cbo_fac1.ListIndex <> -1) Then
For i = 0 To UBound(options)
If (options(i).name = cbo_fac1.List(cbo_fac1.ListIndex)) Then
options(i).isUsed = True
Exit For
End If
Next
End If
If (cbo_fac2.ListIndex <> -1) Then
For i = 0 To UBound(options)
If (options(i).name = cbo_fac2.List(cbo_fac2.ListIndex)) Then
options(i).isUsed = True
Exit For
End If
Next
End If
If (cbo_fac3.ListIndex <> -1) Then
For i = 0 To UBound(options)
If (options(i).name = cbo_fac3.List(cbo_fac3.ListIndex)) Then
options(i).isUsed = True
Exit For
End If
Next
End If
End Sub
选项显式
“选项需要在项目的整个生命周期中保持不变
Dim options()作为列表选项
私有子用户表单_初始化()
'设置选项
调用GetOptions fromWorksheet(“Sheet1”)
使用选项“cbo\U fac1”填写ComboBox
使用选项“cbo\U fac2”填写ComboBox
使用选项“cbo\U fac3”填写ComboBox
端接头
私有子getOptionsFromWorksheet(ByRef wsName作为字符串)
将ws设置为Excel.Worksheet
设置ws=ThisWorkbook.Worksheets(wsName)
'假设数据从A1开始
暗淡的最后一个细胞一样长
我想我会坚持多久
lastCell=ws.Cells.SpecialCells(xlCellTypeLastCell).Row
重拨选项(lastCell-1)
对于i=1到最后一个单元格
options(i-1)=createOption(ws.Cells(i,1.Value)
下一个
端接头
私有函数createOption(ByRef theName)作为listOptions
Dim opt As列表选项
opt.name=名称
opt.isUsed=False
createOption=opt
端函数
私人次级cbo_fac1_AfterUpdate()
呼叫重置选择选项
'使用选项重置其他组合框
使用选项“cbo\U fac2”填写ComboBox
使用选项“cbo\U fac3”填写ComboBox
端接头
私人次级cbo_fac2_AfterUpdate()
呼叫重置选择选项
'使用选项重置其他组合框
使用选项“cbo\U fac1”填写ComboBox
使用选项“cbo\U fac3”填写ComboBox
端接头
私人次级cbo_fac3_更新后()
呼叫重置选择选项
'使用选项重置其他组合框
使用选项“cbo\U fac1”填写ComboBox
使用选项“cbo\U fac2”填写ComboBox
端接头
'使用可用选项重置组合框控件
私有子fillComboBoxWithOptions(ByRef ComboxName)
将selectedItem设置为字符串
'获取并存储所选项目(如果有),
“因此,我们可以在清除并重新填充后重新选择它
如果(Me.Controls(comboBoxName).ListIndex-1),那么
selectedItem=Me.Controls(comboBoxName).List(Me.Controls(comboBoxName).ListIndex)
如果结束
Me.Controls(comboBoxName).清除
我想我会坚持多久
对于i=0到UBound(选项)
如果(选项(i).name=selectedItem),则
控件(comboBoxName).AddItem选项(i).name
ElseIf(不使用选项(i)
控件(comboBoxName).AddItem选项(i).name
如果结束
下一个
'重新选择项目
对于i=0到Me.Controls(comboBoxName).ListCount-1
如果(Me.Controls(comboBoxName).List(i)=selectedItem),则
控件(comboBoxName).ListIndex=i
退出
如果结束
下一个
端接头
专用子重置SelectedOptions()
我想我会坚持多久
对于i=0到UBound(选项)
选项(i).isUsed=False
下一个
'因为列表索引与options()数组的索引不匹配
“我们必须循环,直到找到匹配的名称并设置
'isUsed=True
如果(cbo_fac1.ListIndex-1),则
对于i=0到UBound(选项)
如果(选项(i).name=cbo_fac1.List(cbo_fac1.ListIndex)),则
选项(i).isUsed=True
退出
如果结束
下一个
如果结束
如果(cbo_fac2.ListIndex-1),则
对于i=0到UBound(选项)
如果(选项(i).name=cbo_fac2.List(cbo_fac2.ListIndex)),则
选项(i).isUsed=True
退出
如果结束
下一个
如果结束
如果(cbo_fac3.ListIndex-1),则
对于i=0到UBound(选项)
如果(选项(i).name=cbo_fac3.List(cbo_fac3.ListIndex)),则
选项(i).isUsed=True
退出
如果结束
下一个
如果结束
端接头
这里的想法是,在每个组合框被选择一个值之后,它将使用AferUpdate事件重置其他组合框。它还考虑组合框是否已选择值
希望这有帮助
编辑:
我更改了代码以适应工作表中的数据。我将工作表命名为“Sheet1”(将其更改为您需要的任何内容),我假设在该工作表中,唯一的数据是您希望列出的项目列表(因此,工作表中没有标题,也没有任何其他数据)。您没有说文本是在Hanks bro中的哪一列。我注意到您列出了选项,而不是从电子表格中取出它们。很抱歉,我的代码片段没有说明全部情况。我目前正在从电子表格中提取这些值。这会是个问题吗?以下是我的代码:没问题。这没什么大不了的,只是多了一点代码。