我希望能够在过滤的表格中找到连续行的最大可见区域。我知道一种可能的方式是使用“xlCellTypeVisible”属性循环可见单元格并计算每个可见区域中的单元格。然而,这些数据由数十个甚至数十万个行组成,所以我想知道是否有更快,更有效的方法来做到这一点。在已过滤的范围内查找可见单元格的最大范围
0
A
回答
1
几个月前,我有一个模糊的相似要求,对我发现的最佳解决方案感到不满。盯着你的问题,我突然想到了两种新技术。下面的宏展示了两者。虽然我无法想象技术2不是更快的情况,但两者都给出了可接受的结果。
我的宏启动:
Option Explicit
Sub LargestVisibleRange()
Dim Count As Long
Dim NumRowsInLargestRange As Long
Dim RngCrnt As Range
Dim RngTgt As Range
Dim RowCrnt As Long
Dim RowCrntRangeStart As Long
Dim RowLargestRangeEnd As Long
Dim RowLargestRangeStart As Long
Dim RowMax As Long
Dim RowPrev As Long
Dim StartTime As Single
With Worksheets("TrainData")
RowMax = .Cells(Rows.Count, "A").End(xlUp).Row
Debug.Print "1 RowMax " & RowMax
.Cells.AutoFilter
.Range(.Cells(2, 1), .Cells(RowMax, "Z")).AutoFilter Field:=2, Criteria1:=ChrW$(&H2116) & " 9/10"
我有一些数据时,我与过滤实验我使用。如果你想使用这个宏作为你自己的实验的基础,你将不得不取代上面的陈述。
宏继续:
Set RngTgt = .Range(.Rows(2), .Rows(RowMax)).SpecialCells(xlCellTypeVisible)
Debug.Print "2 RngTgt " & RngTgt.Address
Count = 1
Debug.Print "3 ";
For Each RngCrnt In RngTgt
Debug.Print RngCrnt.Address & " ";
Count = Count + 1
If Count = 30 Then Exit For
Next
Debug.Print
Set RngTgt = RngTgt.EntireRow
Debug.Print "4 RngTgt " & RngTgt.Address
Count = 1
Debug.Print "5 ";
For Each RngCrnt In RngTgt
Debug.Print RngCrnt.Address & " ";
Count = Count + 1
If Count = 30 Then Exit For
Next
Debug.Print
从上面的语句中的输出是:
1 RowMax 5691
2 RngTgt $2:$4,$20:$22,$38:$40,$56:$58,$74:$76,$92:$94,$110:$112,$128:$130,$146:$148,$164:$166,$182:$184,$200:$202,$218:$220,$236:$238,$254:$256,$272:$274,$290:$292,$308:$310,$326:$328,$344:$346,$362:$364,$380:$382,$398:$400,$416:$418,$434:$436,$452:$454,$470:$472
3 $A$2 $B$2 $C$2 $D$2 $E$2 $F$2 $G$2 $H$2 $I$2 $J$2 $K$2 $L$2 $M$2 $N$2 $O$2 $P$2 $Q$2 $R$2 $S$2 $T$2 $U$2 $V$2 $W$2 $X$2 $Y$2 $Z$2 $AA$2 $AB$2 $AC$2
4 RngTgt $2:$4,$20:$22,$38:$40,$56:$58,$74:$76,$92:$94,$110:$112,$128:$130,$146:$148,$164:$166,$182:$184,$200:$202,$218:$220,$236:$238,$254:$256,$272:$274,$290:$292,$308:$310,$326:$328,$344:$346,$362:$364,$380:$382,$398:$400,$416:$418,$434:$436,$452:$454,$470:$472
5 $2:$2 $3:$3 $4:$4 $20:$20 $21:$21 $22:$22 $38:$38 $39:$39 $40:$40 $56:$56 $57:$57 $58:$58 $74:$74 $75:$75 $76:$76 $92:$92 $93:$93 $94:$94 $110:$110 $111:$111 $112:$112 $128:$128 $129:$129 $130:$130 $146:$146 $147:$147 $148:$148 $164:$164 $165:$165
线1示出了,我有5690个的数据行。这比你少得多,但这足以提供足够的性能指标。
线2的结果是:
Set RngTgt = .Range(.Rows(2), .Rows(RowMax)).SpecialCells(xlCellTypeVisible)
Debug.Print "2 RngTgt " & RngTgt.Address
注意,地址范围为$ 2:$ 4,$ 20:$ 22和等。还请注意该行被截断。 Address属性给出尽可能多的整个范围,使得字符串的总长度小于255个字符。
3行的结果是:
Debug.Print "3 ";
For Each RngCrnt In RngTgt
Debug.Print RngCrnt.Address & " ";
Count = Count + 1
If Count = 30 Then Exit For
Next
Debug.Print
注意,虽然范围内的地址分别为整个行,For Each
返回单个细胞。还要注意,尽管我有26列数据,但返回的单元格包括AA2,AB2等。
4号线的结果是:这样看来
Set RngTgt = RngTgt.EntireRow
Debug.Print "4 RngTgt " & RngTgt.Address
,新Set RngTgt
一直没有效果。
但是,第5行与第3行相同,包含行而不是单元格。如果使用Excel 2003,处理修改后的RngTgt
将比处理未修改的RngTgt
快256倍。如果您使用更高版本的Excel,则速度会更快16,384。
宏的其余部分通过两种不同技术中的每一种识别最大范围。第一种技术检查每行的隐藏属性。第二种技术使用修改后的RngTgt
。输出是:
Duration 1: 0.073
Largest range 579 to 582
Duration 2: 0.003
Largest range 579 to 582
我相信持续时间1表明技术1会给出可接受的结果,但技术2显然明显快得多。
的宏的其余部分是:
StartTime = Timer
RowCrntRangeStart = 0 ' No current visible range
RowLargestRangeStart = 0 ' No range found so far
RowCrnt = 2
Do While True
' Search for visible row
Do While True
If Not .Rows(RowCrnt).Hidden Then
RowCrntRangeStart = RowCrnt
Exit Do
End If
RowCrnt = RowCrnt + 1
If RowCrnt > RowMax Then
Exit Do
End If
Loop
If RowCrntRangeStart = 0 Then
' No unprocessed visible row found
Exit Do
End If
' Search for invisble row
Do While True
If .Rows(RowCrnt).Hidden Then
' Visible range is RowCrntRangeStart to RowCrnt-1
If RowLargestRangeStart = 0 Then
' This is the first visible range
RowLargestRangeStart = RowCrntRangeStart
RowLargestRangeEnd = RowCrnt - 1
NumRowsInLargestRange = RowLargestRangeEnd - RowLargestRangeStart + 1
Else
' Check for new range being larger thsn previous
If RowCrnt - RowCrntRangeStart > NumRowsInLargestRange Then
' This visible range is larger than previous largest
RowLargestRangeStart = RowCrntRangeStart
RowLargestRangeEnd = RowCrnt - 1
NumRowsInLargestRange = RowLargestRangeEnd - RowLargestRangeStart + 1
End If
End If
RowCrntRangeStart = 0 ' Not within visible range
RowCrnt = RowCrnt + 1 ' Step over first row of invisible range
Exit Do
End If
RowCrnt = RowCrnt + 1
If RowCrnt > RowMax Then
Exit Do
End If
Loop
If RowCrnt > RowMax Then
Exit Do
End If
Loop
Debug.Print "Duration 1: " & Format(Timer - StartTime, "##0.####")
Debug.Print "Largest range " & RowLargestRangeStart & " to " & RowLargestRangeEnd
End With
StartTime = Timer
RowCrntRangeStart = 0 ' No current visible range
RowLargestRangeStart = 0 ' No range found so far
For Each RngCrnt In RngTgt
If RowCrntRangeStart = 0 Then
' Start of visible range
RowPrev = RngCrnt.Row
RowCrntRangeStart = RowPrev
Else
' Already within visible range
If RowPrev + 1 = RngCrnt.Row Then
' Within same visible range
RowPrev = RngCrnt.Row
Else
' Have start of new visible range
' Last visible range was RowCrntRangeStart to Rowprev
If RowLargestRangeStart = 0 Then
' This is the first visible range
RowLargestRangeStart = RowCrntRangeStart
RowLargestRangeEnd = RowPrev
NumRowsInLargestRange = RowLargestRangeEnd - RowLargestRangeStart + 1
Else
' Check for new range being larger thsn previous
If RowPrev - RowCrntRangeStart + 1 > NumRowsInLargestRange Then
' This visible range is larger than previous largest
RowLargestRangeStart = RowCrntRangeStart
RowLargestRangeEnd = RowPrev
NumRowsInLargestRange = RowLargestRangeEnd - RowLargestRangeStart + 1
End If
End If
RowCrntRangeStart = RngCrnt.Row ' Start of new visible range
RowPrev = RngCrnt.Row
End If
End If
Next
Debug.Print "Duration 2: " & Format(Timer - StartTime, "##0.####")
Debug.Print "Largest range " & RowLargestRangeStart & " to " & RowLargestRangeEnd
End Sub
我希望技术2是对你有帮助。这一定对我有帮助。
相关问题
- 1. 如何在可见范围内找到单元格的值
- 2. 检查所选范围内的单元格是否可见
- 3. Excel VBA根据相对范围的最小值到最大值查找范围内的单元格地址
- 4. 查找范围内的最大和第二大元素
- 5. 查找activecell空单元格范围
- 6. 查找范围内的最小值
- 7. 查找范围内的值
- 8. 价格范围过滤器
- 9. 检查#N/A单元格范围内的空单元格
- 10. 最大范围
- 11. 单元格范围内的宏搜索
- 12. 迭代范围内的单元格
- 13. Google Apps脚本 - 在单元格范围内循环查找值
- 14. 在单元格范围内查找值,然后返回索引
- 15. 当达到最大值时总结范围内的范围和阻塞范围
- 16. VBA使用xlFillSeries自动填充可见单元格(过滤范围)
- 17. 通过合并值过滤的求和单元格范围?
- 18. 仅包含可见数据的单元格的复制范围
- 19. AngularJS过滤范围
- 20. 查找范围
- 21. 从范围VBA中查找最后一个单元格
- 22. php - 检查多个日期范围以查找更大范围内的差距
- 23. 使用范围(单元格,单元格)的VBA中的范围错误设置范围
- 24. 参考单元格范围
- 25. Excel互操作范围查找全部单元格内容
- 26. 查找大范围的所有子范围
- 27. 最后在一个范围内使用的单元格 - excel 2013
- 28. 过滤器的最佳范围
- 29. 通过查找范围
- 30. 可以在单元格内找到的范围内的返回值
感谢您分享解决方案。我发现了另一种使用split为结果数组完成此操作的方法 – EranG