[英]Copying visible/filtered rows efficiently in excel
I am working with some very large datasets (various sheets with 65K+ rows and many columns each). 我正在处理一些非常大的数据集(各具有65K +行和多列的工作表)。 I am trying to write some code to copy filtered data from one sheet to a new empty sheet as fast as possible, but have not had much success so far.
我正在尝试编写一些代码,以将过滤后的数据从一张纸尽可能快地复制到一个新的空纸上,但是到目前为止还没有取得太大的成功。
I can include the rest of the code by request, but all it does is calculates the source and destination ranges (srcRange and destRange). 我可以根据请求包含其余代码,但是它所做的只是计算源和目标范围(srcRange和destRange)。 The time taken to calculate these is negligible.
计算这些时间可以忽略不计。 The vast majority of the time is being spent on this line (4 minutes 50 seconds to be precise):
绝大多数时间都花在了这条线上(准确地说是4分50秒):
srcRange.Rows.SpecialCells(xlCellTypeVisible).Copy Destination:=destRange
Additionally I've tried this: 另外,我已经尝试过了:
destRange.Value = srcRange.Rows.SpecialCells(xlCellTypeVisible).Value
But it doesn't work properly when there's a filter. 但是,当有过滤器时,它将无法正常工作。
Function FastCopy(srcSheet As String, srcCol As String, destSheet As String, destCol As String)
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim srcRange As Range
Dim destRange As Range
Set srcRange = GetColumnRangeByHeaderName(srcSheet, srcCol, -1)
Set destRange = GetColumnRangeByHeaderName(destSheet, destCol, srcRange.Rows.Count)
'destRange.Value = srcRange.Rows.SpecialCells(xlCellTypeVisible).Value
srcRange.Rows.SpecialCells(xlCellTypeVisible).Copy Destination:=destRange
Application.ScreenUpdating = True
Application.Calculation = xlCalculationManual
End Function
This is a slow, dual core machine with 2GB of RAM running excel 2010. Results will obviously vary on a faster machine. 这是一台速度慢的双核计算机,具有2GB RAM,在excel 2010中运行。在速度更快的计算机上,结果显然会有所不同。
Try something like this to work with filtered ranges. 尝试使用类似方法来处理过滤范围。 You're on the right track, the
.Copy
method is expensive and simply writing values from range to range should be much faster, however as you observe, this doesn't work when a range is filtered. 您在正确的轨道上,
.Copy
方法非常昂贵,并且简单地写入范围之间的值应该更快,但是,如您.Copy
,对范围进行过滤时,这是行不通的。 When the range is filtered, you need to iterate the .Areas
in the range's .SpecialCells
: 过滤范围后,您需要迭代范围
.SpecialCells
的.Areas
:
Sub Test()
Dim rng As Range
Dim subRng As Range
Dim destRng As Range
Set destRng = Range("A10")
Set rng = Range("A1:B8").SpecialCells(xlCellTypeVisible)
For Each subRng In rng.Areas
Set destRng = destRng.Resize(subRng.Rows.Count, subRng.Columns.Count)
destRng.Value = subRng.Value
Set destRng = destRng.Cells(destRng.Rows.Count, 1).Resize(1, 1).Offset(1, 0)
Next
End Sub
Modified for your purposes, but untested: 根据您的目的进行了修改,但未经测试:
Function FastCopy(srcSheet As String, srcCol As String, destSheet As String, destCol As String)
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim srcRange As Range
Dim destRange As Range
Dim subRng As Range
Set srcRange = GetColumnRangeByHeaderName(srcSheet, srcCol, -1)
Set destRange = GetColumnRangeByHeaderName(destSheet, destCol, srcRange.Rows.Count)
For Each subRng In srcRange.Areas
Set destRng = destRng.Resize(subRng.Rows.Count, subRng.Columns.Count)
destRng.Value = subRng.Value
Set destRng = destRng.Cells(destRng.Rows.Count, 1).Resize(1, 1).Offset(1, 0)
Next
Application.ScreenUpdating = True
Application.Calculation = xlCalculationManual
End Function
Simplest copying (no filter) 最简单的复制(无过滤器)
Range("F1:F53639").Value = Range("A1:A53639").Value
To expand on my comment 扩大我的评论
Sub Main()
Application.ScreenUpdating = False
' paste the Range into an array
Dim arr
arr = Range("$A$1:$A$53639").Value
' fill the range based on the array
Range("$F$1").Resize(UBound(arr, 1), UBound(arr, 2)) = arr
' apply the same filter to your copied range as the original range
'+ i don't know how you have applied your filter but just re-apply it to column F
' and delete the invisible cells
' unfortunately there is no xlCellTypeHidden or xlCelltypeInvisible hehe so you have to iterate
Dim i As Long
For i = Range("F" & Rows.Count).End(xlUp).Row To 1 Step -1
If (Range("F" & i).EntireRow.Hidden) Then Range("F" & i).Delete
' or Range("F" & i).EntireRow.Delete
Next i
Application.ScreenUpdating = True
End Sub
If you could provide the time it took you to run it that would be great I am very curious 如果您能提供运行它所花费的时间,那太好了,我很好奇
I just ran this code on 53639 rows and it took less than 1 second 我只是在53639行上运行了这段代码,花费了不到1秒的时间
Sub Main()
Application.ScreenUpdating = False
Dim tNow As Date
tNow = Now
' paste the Range into an array
Dim arr
arr = Range("$A$1:$A$53639").Value
' fill the range based on the array
Range("$F$1").Resize(UBound(arr, 1), UBound(arr, 2)) = arr
' apply the same filter to your copied range as the original range
ActiveSheet.Range("$F$1:$F$53640").AutoFilter Field:=1, Criteria1:="a"
' and delete the invisible cells
' unfortunately there is no xlCellTypeHidden or xlCelltypeInvisible hehe so you have to iterate
Dim i As Long
For i = Range("F" & Rows.Count).End(xlUp).Row To 1 Step -1
If (Range("F" & i).EntireRow.Hidden = True) Then
Range("F" & i).Delete
End If
Next i
Debug.Print DateDiff("s", tNow, Now)
Application.ScreenUpdating = True
End Sub
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.