VBA For Loop in Reverse Order: Examples and Common Fixes

VBA & macros · Updated November 3, 2026

VBA For Loop in Reverse Order: Examples and Common Fixes

To run a VBA For loop in reverse order, start the counter at the highest value, set the lowest value as the limit, and use Step -1. For example, For i = 10 To 1 Step -1 visits 10, 9, 8, and so on through 1.

Basic reverse-loop syntax

A VBA For...Next loop normally increases its counter by one. Add a negative step to make it count downward. The general pattern is:

For counter = startValue To endValue Step -1
    ' Run statements for this counter value.
Next counter

The starting value should be greater than or equal to the ending value. Both ends are included when the loop reaches them. If the loop starts at 5 and ends at 1, it runs five times: once for each integer from 5 down to 1. A small complete example is:

Sub CountBackward()
    Dim i As Long

    ' Print the integers from 10 down to 1.
    For i = 10 To 1 Step -1
        Debug.Print i
    Next i
End Sub

In the Visual Basic Editor, Debug.Print sends each value to the Immediate window. This example demonstrates the loop logic; it does not change worksheet data. For a macro that does change a workbook, save a copy first. Excel cannot undo macro actions with Ctrl+Z.

How Step -1 controls the loop

The Step expression determines how much the counter changes after each pass. A step of 1 moves upward by one, while a step of -1 moves downward by one. You can use other negative increments when the values call for them. For example, For i = 20 To 0 Step -5 visits 20, 15, 10, 5, and 0.

VBA checks the loop direction against the limit. With a negative step, the loop can run while the counter is at or above the ending value. If you accidentally use a starting value below the ending value with Step -1, the loop body does not run. For instance, For i = 1 To 10 Step -1 does not count upward; its direction and bounds do not match.

Use an integer variable such as Long for ordinary counts, row numbers, and array indexes. A Long can represent much larger values than VBA’s older Integer type, which matters when working with Excel row numbers. For a step that is a variable, make sure it is not zero: a zero step cannot move the counter toward the limit and can lead to an endless loop.

When counting backward is useful

Reverse loops are especially useful when each pass may remove or shift an item earlier in a sequence. If you delete rows from top to bottom, the remaining rows move up, and the next row number can point to a record you have already passed. Starting at the bottom avoids that shifting problem. Reverse traversal is also useful for processing the newest item first, reading an array from its final element, or undoing a sequence in reverse order.

Choose direction based on the work, not just on whether the data appears sorted. If the loop only reads values and does not modify the collection, either direction may be fine. If it deletes, inserts, or rearranges items, think through what happens to indexes after each change. A backward pass is a common, simple solution for deletions from indexed lists and worksheet rows, although it is not automatically the right choice for every operation.

Looping backward through worksheet rows

This macro checks column A from the last used row up to row 2, treating row 1 as a header, and deletes rows where column A contains the text Closed. It uses the first worksheet in the workbook containing the code. Change that worksheet reference and the tested column to match your layout. Save a copy of the workbook before running it; deleting rows with VBA cannot be reversed with Ctrl+Z.

Sub DeleteClosedRows()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long

    ' Use the first worksheet in this workbook.
    Set ws = ThisWorkbook.Worksheets(1)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    ' Start at the bottom so row deletions do not skip records.
    For i = lastRow To 2 Step -1
        If ws.Cells(i, 1).Value = "Closed" Then
            ws.Rows(i).Delete
        End If
    Next i
End Sub

The End(xlUp) expression finds the last non-empty cell in column A by moving upward from the bottom of that worksheet column. If column A has blanks below the actual data, this still finds its last populated cell. If a different column is more reliable for identifying the final data row, use that column in both places where the code currently uses column number 1.

Starting at row 2 protects the header only if the sheet really has a header in row 1. If there is no header, set the lower limit to 1. Also consider whether the comparison should ignore capitalization or extra spaces; the simple equality test expects the cell value to match Closed. For important data, test on a duplicate sheet first and confirm the rows selected before using a deletion macro on the original.

Reversing an array or collection

For a fixed-size array, use its actual lower and upper bounds rather than assuming the first index is 1. VBA arrays can have different bounds, and arrays created with Array or declared with a custom range may not match an assumed index pattern. The loop below declares a one-based array and prints its values from last to first:

Sub ReadArrayBackward()
    Dim values(1 To 4) As Long
    Dim i As Long

    ' Fill the array with sample values.
    values(1) = 12
    values(2) = 24
    values(3) = 36
    values(4) = 48

    For i = UBound(values) To LBound(values) Step -1
        Debug.Print values(i)
    Next i
End Sub

UBound returns the upper index, and LBound returns the lower index. Using both makes the loop clearer and less dependent on a particular array declaration. For a multidimensional array, specify the dimension when asking for its bounds, such as UBound(data, 2) for the second dimension. The loop must still use the bounds of the dimension being traversed.

A VBA For Each loop does not provide a reverse-order option or a Step clause. If you need to visit a collection backward, use its numeric indexes when the collection supports indexed access, beginning at its count and ending at its first valid index. For a standard VBA Collection, indexes ordinarily run from 1 through Count. Not every object collection behaves identically, so check its documentation and indexing rules.

Common mistakes and how to avoid them

  • Leaving out the negative step: For i = 10 To 1 uses the default positive step, not a reverse step. Write Step -1 explicitly.
  • Reversing the bounds but not the step: A loop from a larger value to a smaller value needs a negative step. A mismatched direction usually means the body is skipped.
  • Using the wrong lower limit: If worksheet data begins on row 2 because row 1 is a heading, end at 2. If it begins on row 1, ending at 2 leaves the first record untouched.
  • Assuming an array starts at zero or one: Use LBound and UBound unless the bounds are deliberately fixed and documented.
  • Changing the counter inside the loop: Avoid assigning a new value to the loop variable within the body. It makes the sequence hard to reason about and can cause skipped or repeated work.
  • Forgetting that rows shift after deletion: Delete from the bottom upward so deleting a row does not move unprocessed rows into indexes the loop has already passed.

It is also worth checking what happens when there is no data below a header. In the worksheet example, if the last used row is 1, the loop has no qualifying row to process, so it does nothing. That is appropriate for a header-only sheet. If a macro has more complicated bounds or several dependent operations, add explicit checks and test empty, one-item, and typical cases.

Reverse For loops compared with alternatives

A reverse For loop is a good fit when the number of passes and index range are known. It makes the start, limit, and direction visible in one line. A forward For loop is often easier to read when processing data that is only being inspected or when operations do not change indexes. Do not reverse a loop just because its output needs to be displayed in reverse; another option is to collect results and present them in the desired order.

A Do While loop can also count backward, but the code must update the counter and maintain its stopping condition correctly. That flexibility is useful when the number of repetitions is not known in advance, but it creates more ways to forget an update or write a condition that never becomes false. When the bounds are known, For...Next usually communicates the intent more directly.

For large ranges in Excel, performance often depends more on how the macro reads and writes cells than on whether the loop counts upward or downward. Repeated worksheet access inside a loop can be slow compared with working with values in memory, but that approach adds complexity and should be chosen only when it suits the task. A reverse loop solves an ordering and index-shift problem; it is not, by itself, a general speed optimization.

Excel platform and macro safety notes

VBA macros run in the desktop versions of Excel for Windows and Mac, but Excel for the web cannot create or run VBA macros. The VBA editor and some object-model features can differ between Windows and Mac, so a macro that uses operating-system-specific components may need adjustments. The basic For...Next syntax and downward counting pattern are the same.

Only enable and run macros from sources you trust. A macro can alter or delete workbook content, and the normal Undo command does not restore those changes. Keep an untouched backup, test on a copy, and inspect the target worksheet and loop bounds before running code that edits cells or deletes rows.

Frequently Asked Questions

How do you write a reverse For loop in VBA?
Set the counter to the highest value, use the lowest value after To, and add Step -1. For example, For i = 5 To 1 Step -1 counts down from 5 to 1.

Does VBA include both the starting and ending numbers?
Yes. A For...Next loop includes a bound when the counter reaches it. A loop from 5 to 1 with a step of -1 includes both 5 and 1.

Why does my reverse VBA loop not run?
Check that the starting value is greater than or equal to the ending value and that the step is negative. A start below the limit with Step -1 does not form a downward range, so the loop body is skipped.

Can I use Step -2 or another negative number?
Yes. A negative step can be any appropriate nonzero amount. For example, For i = 10 To 0 Step -2 visits 10, 8, 6, 4, 2, and 0.

Should I loop backward when deleting Excel rows?
Usually, yes, when deleting rows one at a time by index. Begin at the last relevant row and move upward so deleting a row does not shift a not-yet-checked row past the loop. Test the macro on a copy first because deletion by VBA cannot be undone with Ctrl+Z.

Related

Try it: the Column Letter to Number: aA is 27, XFD is 16,384. Converts both ways.

More in VBA & macros

Sources: Function behaviour and menu paths: Microsoft Support documentation for Excel. Method & sources

Spotted an error in this guide? Let us know.