用于填充 ListBox 的过滤数据数组
Array of filtered data to populate ListBox
好的,我正在按以下条件筛选 sheet ("Data"):
Sub Filter_Offene()
Sheets("Data").Range("A:R").AutoFilter Field:=18, Criteria1:="WAHR"
End Sub
然后,我想将过滤后的 Table 填充到列表框
我的问题是,行数可能会有所不同,所以我想我可以通过执行此 cells.find 例程来尝试列出过滤的 table "ends" 的位置:
Dim lRow As Long
Dim lCol As Long
lRow = ThisWorkbook.Sheets("Data").Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
lRow = lRow + 1
不幸的是,这也计算了 "hidden" 行,所以在我的例子中它不是 2 而是 7..
我以前用过.Range.SpecialCells(xlCellTypeVisible)
,但它似乎对上面的cells.find不起作用。
有人知道如何计算可见(=过滤)Table,然后将其放入列表框吗?
编辑:我像这样填充列表框(未过滤):
Dim lastrow As Long
With Sheets("Data")
lastrow = .Cells(.Rows.Count, "R").End(xlUp).Row
End With
With Offene_PZ_Form.Offene_PZ
.ColumnCount = 18
.ColumnWidths = "0;80;0;100;100;0;50;50;80;50;0;0;0;0;0;150;150;0"
.List = Sheets("Data").Range("A2:R" & lastrow).Value
End With
但这不适用于过滤后的数据。
这是一个有趣的小事实,一旦您开始过滤数据,Excel
就会创建一个 hidden named range。如果您有连续数据 (headers/rows),这将 return 您的范围而无需查找。尽管它看起来像 UsedRange
,但搜索您最后使用的列和行并创建您自己的 Range
变量进行过滤可能仍然更好。对于这个练习,我将保留它。此外,如上面的评论所示,可以遍历 Areas
个可见单元格。我建议事先检查一下,以确保除了 headers.
之外还有过滤数据
Sub Test()
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Data")
Dim Area as Range
ws.Cells(1, 1).AutoFilter 18, "WAHR"
With ws.Range("_FilterDatabase")
If .SpecialCells(12).Count > .Columns.Count Then
For Each Area In .Offset(1).Resize(.Rows.Count - 1, .Columns.Count).SpecialCells(12).Areas
Debug.Print Area.Address 'Do something
Next
End If
End With
End Sub
如果没有 headers 明显缺失,以上方法有效。
如果你想使用一个连续的(内置的)数组,请尝试下一个代码。也可以从不连续的范围地址构建它:
Sub Filter_Offene()
Dim sh As Worksheet, lastRow As Long, rngFilt As Range, arrFin As Variant
Set sh = Sheets("Data")
lastRow = sh.Range("R" & Rows.count).End(xlUp).Row
rngFilt.AutoFilter field:=18, Criteria1:="WAHR"
Set rngFilt = rngFilt.Offset(1).SpecialCells(xlCellTypeVisible)
arrFin = ContinuousArray(rngFilt, sh, "R:R")
With ComboBox1
.list = arrFin
.ListIndex = 0
End With
End Sub
Private Function ContinuousArray(rngFilt As Range, sh As Worksheet, colLet As String) As Variant
Dim arrFilt As Variant, El As Variant, arFin As Variant
Dim rowsNo As Long, k As Long, i As Long, j As Long, arrInt As Variant
arrFilt = Split(rngFilt.address, ",")' Obtain an array of areas addresses
'real number of rows of the visible cells range:
For Each El In arrFilt
rowsNo = rowsNo + Range(El).Rows.count
Next
'redim the final array at the number of rows
ReDim arFin(1 To rowsNo, 1 To rngFilt.Columns.count)
rowsNo = 1
For Each El In arrFilt 'Iterate between the areas addresses
rowsNo = Range(El).Rows.count 'number of rows of the area
arrInt = ActiveSheet.Range(El).value' put the area range in an array
For i = 1 To UBound(arrInt, 1) 'fill the final array
k = k + 1
For j = 1 To rngFilt.Columns.count
arFin(k, j) = arrInt(i, j)
Next j
Next i
Next
ContinuousArray = arFin
End Function
这里是一个 VBA 代码,用于使用过滤后的行填充 UserForm1.ListBox1.List
。
感谢@FaneDuru 根据他的评论对代码进行了改进。
在 Userform1 代码中
Private Sub UserForm_Initialize()
PopulateListBoxWithVisibleCells
End Sub
在模块中
Sub PopulateListBoxWithVisibleCells()
Dim wb As Workbook, ws As Worksheet
Dim filtRng As Range, rw As Range
Dim i As Long, j As Long, x As Long, y As Long, k As Long, filtRngArr
i = 0: j = 0: x = 0: y = 0
Set wb = ThisWorkbook: Set ws = wb.Sheets("Sheet1")
Set filtRng = ws.UsedRange.Cells.SpecialCells(xlCellTypeVisible)
For Each Area In filtRng.Areas
x = x + Area.Rows.Count
Next
y = filtRng.Columns.Count
ReDim filtRngArr(1 To x, 1 To y)
For k = 1 To filtRng.Areas.Count
For Each rw In filtRng.Areas(k).Rows
i = i + 1
arr = rw.Value
For j = 1 To y
filtRngArr(i, j) = Split(Join(Application.Index(arr, 1, 0), "|"), "|")(j - 1)
Next
Next
Next
With UserForm1.ListBox1
.ColumnCount = y
.List = filtRngArr
End With
End Sub
我们还可以添加更多字段,例如 Split(rw.Row & "|" & Join(Application.Index(arr, 1, 0), "|"), "|")(j - 1)
这样的行号,但是对于每个这样的预期列增量,我们需要增加 y 的值,例如 y = filtRng.Columns.Count + 1
为了找到 x(行数)我们不需要第一个循环...简单地说,x = filtRng.Cells.Count / filtRng.Columns.Count
就足够了
好的,我正在按以下条件筛选 sheet ("Data"):
Sub Filter_Offene()
Sheets("Data").Range("A:R").AutoFilter Field:=18, Criteria1:="WAHR"
End Sub
然后,我想将过滤后的 Table 填充到列表框 我的问题是,行数可能会有所不同,所以我想我可以通过执行此 cells.find 例程来尝试列出过滤的 table "ends" 的位置:
Dim lRow As Long
Dim lCol As Long
lRow = ThisWorkbook.Sheets("Data").Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
lRow = lRow + 1
不幸的是,这也计算了 "hidden" 行,所以在我的例子中它不是 2 而是 7..
我以前用过.Range.SpecialCells(xlCellTypeVisible)
,但它似乎对上面的cells.find不起作用。
有人知道如何计算可见(=过滤)Table,然后将其放入列表框吗?
编辑:我像这样填充列表框(未过滤):
Dim lastrow As Long
With Sheets("Data")
lastrow = .Cells(.Rows.Count, "R").End(xlUp).Row
End With
With Offene_PZ_Form.Offene_PZ
.ColumnCount = 18
.ColumnWidths = "0;80;0;100;100;0;50;50;80;50;0;0;0;0;0;150;150;0"
.List = Sheets("Data").Range("A2:R" & lastrow).Value
End With
但这不适用于过滤后的数据。
这是一个有趣的小事实,一旦您开始过滤数据,Excel
就会创建一个 hidden named range。如果您有连续数据 (headers/rows),这将 return 您的范围而无需查找。尽管它看起来像 UsedRange
,但搜索您最后使用的列和行并创建您自己的 Range
变量进行过滤可能仍然更好。对于这个练习,我将保留它。此外,如上面的评论所示,可以遍历 Areas
个可见单元格。我建议事先检查一下,以确保除了 headers.
Sub Test()
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Data")
Dim Area as Range
ws.Cells(1, 1).AutoFilter 18, "WAHR"
With ws.Range("_FilterDatabase")
If .SpecialCells(12).Count > .Columns.Count Then
For Each Area In .Offset(1).Resize(.Rows.Count - 1, .Columns.Count).SpecialCells(12).Areas
Debug.Print Area.Address 'Do something
Next
End If
End With
End Sub
如果没有 headers 明显缺失,以上方法有效。
如果你想使用一个连续的(内置的)数组,请尝试下一个代码。也可以从不连续的范围地址构建它:
Sub Filter_Offene()
Dim sh As Worksheet, lastRow As Long, rngFilt As Range, arrFin As Variant
Set sh = Sheets("Data")
lastRow = sh.Range("R" & Rows.count).End(xlUp).Row
rngFilt.AutoFilter field:=18, Criteria1:="WAHR"
Set rngFilt = rngFilt.Offset(1).SpecialCells(xlCellTypeVisible)
arrFin = ContinuousArray(rngFilt, sh, "R:R")
With ComboBox1
.list = arrFin
.ListIndex = 0
End With
End Sub
Private Function ContinuousArray(rngFilt As Range, sh As Worksheet, colLet As String) As Variant
Dim arrFilt As Variant, El As Variant, arFin As Variant
Dim rowsNo As Long, k As Long, i As Long, j As Long, arrInt As Variant
arrFilt = Split(rngFilt.address, ",")' Obtain an array of areas addresses
'real number of rows of the visible cells range:
For Each El In arrFilt
rowsNo = rowsNo + Range(El).Rows.count
Next
'redim the final array at the number of rows
ReDim arFin(1 To rowsNo, 1 To rngFilt.Columns.count)
rowsNo = 1
For Each El In arrFilt 'Iterate between the areas addresses
rowsNo = Range(El).Rows.count 'number of rows of the area
arrInt = ActiveSheet.Range(El).value' put the area range in an array
For i = 1 To UBound(arrInt, 1) 'fill the final array
k = k + 1
For j = 1 To rngFilt.Columns.count
arFin(k, j) = arrInt(i, j)
Next j
Next i
Next
ContinuousArray = arFin
End Function
这里是一个 VBA 代码,用于使用过滤后的行填充 UserForm1.ListBox1.List
。
感谢@FaneDuru 根据他的评论对代码进行了改进。
在 Userform1 代码中
Private Sub UserForm_Initialize()
PopulateListBoxWithVisibleCells
End Sub
在模块中
Sub PopulateListBoxWithVisibleCells()
Dim wb As Workbook, ws As Worksheet
Dim filtRng As Range, rw As Range
Dim i As Long, j As Long, x As Long, y As Long, k As Long, filtRngArr
i = 0: j = 0: x = 0: y = 0
Set wb = ThisWorkbook: Set ws = wb.Sheets("Sheet1")
Set filtRng = ws.UsedRange.Cells.SpecialCells(xlCellTypeVisible)
For Each Area In filtRng.Areas
x = x + Area.Rows.Count
Next
y = filtRng.Columns.Count
ReDim filtRngArr(1 To x, 1 To y)
For k = 1 To filtRng.Areas.Count
For Each rw In filtRng.Areas(k).Rows
i = i + 1
arr = rw.Value
For j = 1 To y
filtRngArr(i, j) = Split(Join(Application.Index(arr, 1, 0), "|"), "|")(j - 1)
Next
Next
Next
With UserForm1.ListBox1
.ColumnCount = y
.List = filtRngArr
End With
End Sub
我们还可以添加更多字段,例如 Split(rw.Row & "|" & Join(Application.Index(arr, 1, 0), "|"), "|")(j - 1)
这样的行号,但是对于每个这样的预期列增量,我们需要增加 y 的值,例如 y = filtRng.Columns.Count + 1
为了找到 x(行数)我们不需要第一个循环...简单地说,x = filtRng.Cells.Count / filtRng.Columns.Count
就足够了