簡體   English   中英

Excel VBA UsedRange用於多個FOR循環,並“重置”以使宏更快

[英]Excel VBA UsedRange for multiple FOR loops, and “resetting” to make macro faster

我已經開發了一個宏來清除復制/粘貼的數據集,這些數據只是Excel中具有多個列和標題的一系列行。 為了幫助清理數據,我向以下添加了三個FOR LOOP流程:

  1. 刪除編號為項目符號的行
  2. 刪除多余的數據(英里和分鍾有效)
  3. 手動將其他數據集剪切/粘貼到各自的列中(steps和stepavg)

看來效果很好,但是我想優化流程。 在運行宏時,問題是我使用“ 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)不要使用變量,除非您要多次使用它。 maxRowmaxRow2maxRow3是沒有意義的。 每個新變量都會增加您的應用程序正在使用的內存(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=falseApplication.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM