我试图加快VBA拥有25000名行项目的环
我有一个拥有25000名行其下台通过电子数据表的代码。现在,每个小区还以为代码回路,看看上一个单元格的值匹配当前单元格的值。如果它们不匹配它插入一个新的空白行。眼下的代码需要5个多小时才能完成一个非常快的计算机上。有没有什么办法可以加快这个吗?
With ActiveSheet
BottomRow4 = .Cells(.Rows.Count, "E").End(xlUp).Row
End With
Do
Cells(ActiveCell.Row, 5).Select
Do
ActiveCell.Offset(1, 0).Select
'Determines if previous cells is the same as current cells
Loop Until (ActiveCell.Offset(0, -1) & ActiveCell <>
ActiveCell.Offset(1, -1) & ActiveCell.Offset(1, 0))
'Insert Blank Row if previous cells do not match current cells...
Rows(ActiveCell.Offset(1, 0).Row & ":" & ActiveCell.Offset(1,
0).Row).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
BottomRow4 = BottomRow4 + 1
Loop Until ActiveCell.Row >= BottomRow4
删除行的时候同样,你可以保存你的插入,直到你完成循环。
在塔的顶部选择一个单元格后,运行要插入的(但不是排1):
Sub Tester()
Dim c As Range, rngIns As Range, sht As Worksheet
Dim offSet As Long, cInsert As Range
Set sht = ActiveSheet
For Each c In sht.Range(Selection, _
sht.Cells(sht.Rows.Count, Selection.Column).End(xlUp)).Cells
offSet = IIf(offSet = 0, 1, 0) '<< toggle offset
If c.offSet(-1, 0).Value <> c.Value Then
'This is a workaround to prevent two adjacent cells from merging in
' the rngInsert range being built up...
Set cInsert = c.offSet(0, offSet)
If rngIns Is Nothing Then
Set rngIns = cInsert
Else
Set rngIns = Application.Union(cInsert, rngIns)
End If
End If
Next c
If Not rngIns Is Nothing Then
rngIns.EntireRow.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
End If
End Sub
编辑:在使用="Val_" & ROUND(RAND()*1000)
填充25K行3秒运行时,转换为值,则排序。
Sub InsertIfNotEqual()
Const cSheet As Variant = 1 ' Worksheet Name/Index
Const cFirstR As Long = 5 ' First Row
Const cCol As Variant = "E" ' Last-Row-Column Letter/Number
Dim rng As Range ' Last Cell Range, Union Range
Dim vntS As Variant ' Source Array
Dim vntT As Variant ' Target Array
Dim i As Long ' Source Array Row Counter
Dim j As Long ' Target Array Row Counter
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
On Error GoTo ProcedureExit
' In Worksheet
With ThisWorkbook.Worksheets(cSheet)
' Determine the last used cell in Last-Row-Column.
Set rng = .Columns(cCol).Find("*", , xlFormulas, , , xlPrevious)
' Copy Column Range to Source Array.
vntS = .Cells(cFirstR, cCol).Resize(rng.Row - cFirstR + 1)
End With
' In Arrays
' Resize 1D Target Array to the first dimension of 2D Source Array.
ReDim vntT(1 To UBound(vntS)) As Long
' Loop through rows of Source Array.
For i = 2 To UBound(vntS)
' Check if current value is equal to previous value.
If vntS(i, 1) <> vntS(i - 1, 1) Then
' Increase row of Target Array.
j = j + 1
' Write Source Range Next Row Number to Target Array.
vntT(j) = i + cFirstR
End If
Next
' If no non-equal data was found.
If j = 0 Then Exit Sub
' Resize Target Array to found "non-equal data count".
ReDim Preserve vntT(1 To j) As Long
' In Worksheet
With ThisWorkbook.Worksheets(cSheet)
' Set Union range to first cell of row in Target Array.
Set rng = .Cells(vntT(1), 2)
' Check if there are more rows in Target Array.
If UBound(vntT) > 1 Then
' Loop through the rest of the rows (other than 1) in Target Array.
For i = 2 To UBound(vntT)
' Add corresponding cells to Union Range. To prevent the
' creation of "consecutive" ranges by Union, the resulting
' cells to be added are alternating between column A and B
' (1 and 2) using the Mod operator against the Target Array
' Row Counter divided by 2.
Set rng = Union(rng, .Cells(vntT(i), 1 + i Mod 2))
Next
End If
' Insert blank rows in one go.
rng.EntireRow.Insert
End With
ProcedureExit:
With Application
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
编辑:增加了两个选项:没有测试的速度。我想测试2()本来是快,但我不能肯定这取决于行数。
未经检验的,但只是我想的快。如果我会记得我会回来这以后,因为我觉得有更快的方法
Sub Test1()
Dim wsSheet As Worksheet
Dim arrSheet() As Variant
Dim collectRows As New Collection
Dim rowNext As Long
Application.ScreenUpdating = False
Application.EnableEvents = False
Const ColCheck As Integer = 6
Set wsSheet = ActiveSheet
arrSheet = wsSheet.Range("A1").CurrentRegion
For rowNext = UBound(arrSheet, 1) To LBound(arrSheet, 1) + 1 Step -1
If arrSheet(rowNext, ColCheck) <> arrSheet(rowNext - 1, ColCheck) Then collectRows.Add rowNext
Next rowNext
For rowNext = 1 To collectRows.Count
wsSheet.Cells(collectRows(rowNext), 1).EntireRow.Insert
Next rowNext
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
第二个选项将一次全部:我用一个字符串这里是因为联盟会改变彼此相邻行成一个更大的范围内。取而代之的范围(“1:1”,“2:2”),它会创建(“1:2”),这将不插入你需要的方式。我不知道一个更清洁的方式,但也有可能是。
Sub Test2()
Dim wsSheet As Worksheet
Dim arrSheet() As Variant
Dim collectRows As New Collection
Dim rowNext As Long
Dim strRange As String
Dim cntRanges As Integer
Dim rngAdd As Range
Application.ScreenUpdating = False
Application.EnableEvents = False
Const ColCheck As Integer = 6
Set wsSheet = ActiveSheet
arrSheet = wsSheet.Range("A1").CurrentRegion
For rowNext = UBound(arrSheet, 1) To LBound(arrSheet, 1) + 1 Step -1
If arrSheet(rowNext, ColCheck) <> arrSheet(rowNext - 1, ColCheck) Then
strRange = wsSheet.Cells(rowNext, 1).EntireRow.Address & "," & strRange
cntRanges = cntRanges + 1
If cntRanges > 10 Then
collectRows.Add Left(strRange, Len(strRange) - 1)
strRange = vbNullString
cntRanges = 0
End If
End If
Next rowNext
If collectRows.Count > 0 Then
Dim i As Long
For i = 1 To collectRows.Count
Set rngAdd = Range(collectRows(i))
rngAdd.Insert
Next i
End If
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub