如何用工作表筛选后的可见区域填充UserForm列表框?报错380
解决ListBox绑定筛选后可见区域的错误380问题
首先,你遇到的错误380根源很明确:筛选后的可见区域是由多个不连续的单元格区域(Areas)组成的,而ListBox的RowSource属性只能绑定连续的单元格区域,直接赋值不连续区域的地址自然会报错。另外你的代码里还有个小bug:startRow和lastRow的获取逻辑搞反了,这也会导致后续区域选取出错。
下面给你两个高效的解决方案,优先推荐第一个数组方案:
方案1:用二维数组填充(最高效)
筛选后的区域不连续,我们需要遍历每个独立的Area,把数据逐行存入动态数组,最后直接赋值给ListBox的List属性(这个属性支持二维数组,效率比循环AddItem高很多)。
修正后的完整代码:
Private Sub listBox_Change() Dim startRow As Integer, lastRow As Integer Dim sht As Worksheet Dim dataRng As Range, area As Range Dim myArray() As Variant Dim arrRow As Integer, r As Range Set sht = Worksheets("SheetName") Call filterData(sht) '执行数据筛选 ' 获取筛选后的数据区域(跳过表头,假设表头在第1行) On Error Resume Next '防止筛选后无可见数据导致报错 Set dataRng = sht.Range("A2:D" & sht.Cells(Rows.Count, 1).End(xlUp).Row).SpecialCells(xlCellTypeVisible) On Error GoTo 0 If dataRng Is Nothing Then userForm.listBox.Clear '无数据时清空ListBox Exit Sub End If ' 初始化数组:行数为可见区域总行数,列数固定为4 ReDim myArray(1 To dataRng.Rows.Count, 1 To 4) arrRow = 1 ' 遍历每个不连续区域,把数据存入数组 For Each area In dataRng.Areas For Each r In area.Rows myArray(arrRow, 1) = r.Cells(1).Value myArray(arrRow, 2) = r.Cells(2).Value myArray(arrRow, 3) = r.Cells(3).Value myArray(arrRow, 4) = r.Cells(4).Value arrRow = arrRow + 1 Next r Next area ' 填充ListBox With userForm.listBox .Clear .ColumnCount = 4 .ColumnWidths = "90;90;0;90" .List = myArray '直接赋值数组,效率拉满 End With End Sub
关键点说明:
- 加入了错误处理,避免筛选后无数据时程序崩溃
- 遍历每个
Area的每一行,确保所有可见数据都被正确收集 List属性直接接受二维数组,大数据量下比循环添加快得多
方案2:用AddItem循环添加(更直观)
如果觉得数组操作有点绕,也可以用AddItem结合循环逐个添加行数据,逻辑更直白:
Private Sub listBox_Change() Dim sht As Worksheet Dim dataRng As Range, r As Range Set sht = Worksheets("SheetName") Call filterData(sht) On Error Resume Next Set dataRng = sht.Range("A2:D" & sht.Cells(Rows.Count, 1).End(xlUp).Row).SpecialCells(xlCellTypeVisible) On Error GoTo 0 With userForm.listBox .Clear .ColumnCount = 4 .ColumnWidths = "90;90;0;90" If Not dataRng Is Nothing Then For Each r In dataRng.Rows .AddItem r.Cells(1).Value '添加第一列内容 .List(.ListCount - 1, 1) = r.Cells(2).Value '设置第二列 .List(.ListCount - 1, 2) = r.Cells(3).Value '设置第三列 .List(.ListCount - 1, 3) = r.Cells(4).Value '设置第四列 Next r End If End With End Sub
为什么你之前的数组方案失败?
你之前直接用MyArray(i, j) = dataRng.Cells(i, j).Value,但dataRng.Cells(i,j)的索引是相对于整个可见区域的,不是工作表的行号。当区域不连续时,这个索引逻辑会混乱,必须通过遍历每一行来逐个赋值才能保证数据正确。
如果需要包含表头,只需要在填充数组/循环添加前,先把表头行的数据加入到ListBox的第一行即可。
内容的提问来源于stack exchange,提问作者fpuglap
相关产品推荐
相关产品推荐

