[英]Excel VBA UsedRange for multiple FOR loops, and “resetting” to make macro faster
我已經開發了一個宏來清除復制/粘貼的數據集,這些數據只是Excel中具有多個列和標題的一系列行。 為了幫助清理數據,我向以下添加了三個FOR LOOP流程:
看來效果很好,但是我想優化流程。 在運行宏時,問題是我使用“ UsedRange”來計算FOR LOOP 1的行數(大約800行)。 在該循環中,刪除了許多行,因此可以從800過濾到350。然后在執行FOR LOOP 2時,似乎UsedRange仍然引用800行,因此循環繼續進行,從350過濾到65。最后使用FOR LOOP 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
首先,這里有一些提示:
1)不要使用變量,除非您要多次使用它。 maxRow
, maxRow2
和maxRow3
是沒有意義的。 每個新變量都會增加您的應用程序正在使用的內存(RAM)數量。 在某些時候,VBA的“垃圾收集器”將會出現並進一步降低您的代碼速度。 由於這個原因,使用大量變量是不好的做法,但是減少這些不必要的變量的數量也可以提高可讀性並減少混亂。
2)定義循環變量時,無需為每個循環定義3個單獨的變量。 始終使用相同的內容。 使用多個循環變量的唯一原因是使用嵌套循環。 例如
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"
與
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)刪除整行數據時,不需要移位(除非您想向下移動數據)。 因此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
。 更復雜的效率包括批量刪除行,而不是逐行刪除。 例如
'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
但是我離題,前者可能對您來說足夠快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.