我开发了一个宏来清理复制/粘贴数据集,这些数据只是一系列包含多个列和标题的Excel行。为了帮助清理数据,我已经将三个FOR LOOP流程添加到:
它似乎运作良好,但我想优化这个过程。在运行宏时,问题在于我使用了" UsedRange"找出FOR LOOP 1(约800行)有多少行。在该循环期间,许多行被删除,因此它可以从800过滤到350.然后当执行FOR LOOP 2时,似乎UsedRange仍然引用800行,因此循环继续,从350过滤到65.最后使用FOR循环3,它成功地完成所有65个并完成,我可以告诉它完成了。但是,它会继续排800!
对"明确"的任何建议或"重置" UsedRange所以这个过程更快?除了这个问题,我的宏工作得很好。
'Cleaning the Data
Dim i As Long
Dim j As Long
Dim k As Long
Dim maxRow As Long
maxRow = ActiveSheet.UsedRange.Rows.Count
'Removes all those single number rows
For i = 2 To maxRow Step 3
Rows(i).Select
Selection.Delete Shift:=xlLeft
Next i
Range("A1").Select
'Removes all those miles and min active data
Dim maxRow2 As Long
maxRow2 = ActiveSheet.UsedRange.Rows.Count
For j = 5 To maxRow2 Step 3
Range(Rows(j), Rows(j + 5)).Select
Selection.Delete Shift:=x1Up
Next j
Range("A1").Select
'Cut/paste the Steps and StepsAvg data
Dim maxRow3 As Long
maxRow3 = ActiveSheet.UsedRange.Rows.Count
For k = 3 To maxRow Step 1
Cells(k, 1).Select
Selection.Cut
Cells(k - 1, 2).Select
ActiveSheet.Paste
Cells(k + 1, 1).Select
Selection.Cut
Cells(k - 1, 3).Select
ActiveSheet.Paste
Range(Rows(k), Rows(k + 1)).Select
Selection.Delete Shift:=x1Up
Next k
答案 0 :(得分:1)
首先,这里有几点建议:
1)除非您要多次使用变量,否则不要使用变量。 maxRow
,maxRow2
和maxRow3
毫无意义。每个新变量都会增加应用程序使用的内存量(RAM)。在某些时候,VBA的“垃圾收集器”会出现,并且会使代码更慢。由于这个原因,使用大量变量是不好的做法,但减少这些不必要变量的数量也可以提高可读性并减少混乱。
2)定义循环变量时,不需要为每个循环定义3个单独的变量。始终使用相同的一个。使用多个循环变量的唯一原因是您使用的是嵌套循环。 E.G。
for i = 1 to 10
for j = 2 to 5
for k = 3 to 7
debug.print i & "," & j & "," & k
next k
next j
next i
3)您无需选择要操作的单元格。以下陈述是等效的:
cells(1,1).select
selection.value = "hello"
v.s。
cells(1,1).value = "hello"
虽然在这种情况下速度可以忽略不计,但在区域上循环时,直接设置值比选择单元格然后设置值要快得多。
4)要将值从一个单元格传输到另一个单元格,您不需要使用剪切和粘贴:
cells(1,1).cut
cells(2,1).select
activesheet.paste
(几乎)与
相同cells(2,1).value = cells(1,1).value 'doesn't copy formatting or formula! I assume this isn't required.
5)删除整行数据时不需要Shift(除非您想要向下移动数据)。因此,rows(i).delete Shift:=x1Up
可以简化为rows(i).delete
将所有这些放在一起你会得到这个,在我看来,它更具可读性并且速度更快:
Dim i As Long
'Removes all those single number rows
For i = 2 To ActiveSheet.UsedRange.Rows.Count Step 3
Rows(i).Delete
Next i
'Removes all those miles and min active data
For i = 5 To ActiveSheet.UsedRange.Rows.Count Step 3
Range(Rows(i), Rows(i + 5)).Delete
Next i
'Cut/paste the Steps and StepsAvg data
For i = 3 To ActiveSheet.UsedRange.Rows.Count Step 1
Cells(i - 1, 2).Value = Cells(i, 1).Value
Cells(i - 1, 3).Value = Cells(i + 1, 1).Value
Range(Rows(i), Rows(i + 1)).Delete
Next i
为提高速度还有很多工作要做。例如Application.ScreenUpdating=false
和Application.EnableEvents=False
。更复杂的效率包括批量删除行而不是逐行删除。 E.G。
'Removes all those single number rows
Dim rng as range: set rng = Rows(2)
For i = 5 To ActiveSheet.UsedRange.Rows.Count Step 3
set rng = Application.union(rng,Rows(i))
Next i
rng.Delete
尽管代码看起来更复杂,但它也更快,因为您在批量执行更多行。另一种选择是使用数组而不是范围,这可能是最快的方法,但会更加复杂。
dim myArray as variant: myArray = Activesheet.UsedRange.Value
'do stuff with array
ActiveSheet.Clear
ActiveSheet.range(cells(1,1),cells(ubound(myArray,1),ubound(myArray,2)).value = myArray
但我离题前者很可能对你来说足够快。