Reverse order of For Each loop Reverse order of For Each loop vba vba

Reverse order of For Each loop


It's not possible to loop backwards using the for each loop syntax.

As an alternative you can use a For i = a To 1 Step -1 loop:

Sub reverseForEach()    Dim i As Long, rng As Range    Set rng = ActiveSheet.Range("A1:B2")    For i = rng.Cells.Count To 1 Step -1        Debug.Print rng.item(i).Address        ' Or shorthand rng(i) as the Item property         ' is the default property for the Range object.        ' Prints: $B$2, $A$2, $B$1, $A$1    Next iEnd Sub

This works with all collections that have the Item property. For instance Worksheets, Areas or Shapes.

Note: The order of the loop when using on the Range object is from right to left, then up.


For built in collections (eg a Range) the short answer is: you can't. For user defined collections the answer linked by @VBlades might be useful, although the cost might outweigh the benifit.

One work around is to seperate the identification of items to be removed from the actual removal. Eg, for a range, build up a new range variable using Union, then process that variable, eg delete all the rows in one go. For the Range example, you can also take advantage of the Variant Array method to further speed things up.

Whether or not any of this is useful will depend on your actual use case.


There are other good answers but here's another alternative method of "stepping backwards" through a Range.


Function to Invert Range into Array

This function returns a "backwards Range Array" that can be used with For..Each:

Function ReverseRange(rg As Range) As Range()    Dim arr() As Range, r As Long, c As Long, n As Long    With rg        ReDim arr(1 To .Cells.Count) 'resize Range Array        For r = .Cells(.Rows.Count, 1).Row To .Cells(1, 1).Row Step -1            For c = .Cells(1, .Columns.Count).Column To .Cells(1, 1).Column Step -1                n = n + 1                Set arr(n) = .Worksheet.Cells(r, c) 'set cell in Array            Next c        Next r    End With    ReverseRange = arr  'return Range Array as function resultEnd Function

Example Usage:

Sub test()    Dim oCell    For Each oCell In ReverseRange(ActiveSheet.Range("E5:A1"))        Debug.Print oCell.Address 'do something here with each cell    Next oCellEnd Sub