Цикл For Each… Next в VBA Excel, его синтаксис и описание отдельных компонентов. Примеры использования цикла For Each… Next.
Цикл For Each… Next в VBA Excel предназначен для выполнения блока операторов по отношению к каждому элементу из группы элементов (диапазон, массив, коллекция). Этот замечательный цикл применяется, когда неизвестно количество элементов в группе и их индексация, в противном случае, более предпочтительным считается использование цикла For…Next.
For Each element In group [ statements ] [ Exit For ] [ statements ] Next [ element ] |
В квадратных скобках указаны необязательные атрибуты цикла For Each… Next.
Компоненты цикла For Each… Next
Компонент | Описание |
---|---|
element | Обязательный атрибут в операторе For Each, необязательный атрибут в операторе Next. Представляет из себя переменную, используемую для циклического прохода элементов группы (диапазон, массив, коллекция), которая предварительно должна быть объявлена с соответствующим типом данных*. |
group | Обязательный атрибут. Группа элементов (диапазон, массив, коллекция), по каждому элементу которой последовательно проходит цикл For Each… Next. |
statements | Необязательный** атрибут. Операторы вашего кода. |
Exit For | Необязательный атрибут. Оператор выхода из цикла до его окончания. |
*Если цикл For Each… Next используется в VBA Excel для прохождения элементов коллекции (объект Collection) или массива, тогда переменная element должна быть объявлена с типом данных Variant, иначе цикл работать не будет.
**Если не использовать в цикле свой код, смысл применения цикла теряется.
Примеры циклов For Each… Next
Цикл для диапазона ячеек
На активном листе рабочей книги Excel выделите диапазон ячеек и запустите на выполнение следующую процедуру:
Sub test1() Dim element As Range, a As String a = «Данные, полученные с помощью цикла For Each… Next:» For Each element In Selection a = a & vbNewLine & «Ячейка « & element.Address & _ » содержит значение: « & CStr(element.Value) Next MsgBox a End Sub |
Информационное окно MsgBox выведет адреса выделенных ячеек и их содержимое, если оно есть. Если будет выбрано много ячеек, то полностью информация по всем ячейкам выведена не будет, так как максимальная длина параметра Prompt функции MsgBox составляет примерно 1024 знака.
Цикл для коллекции листов
Скопируйте следующую процедуру VBA в стандартный модуль книги Excel:
Sub test2() Dim element As Worksheet, a As String a = «Список листов, содержащихся в этой книге:» For Each element In Worksheets a = a & vbNewLine & element.Index _ & «) « & element.Name Next MsgBox a End Sub |
Информационное окно MsgBox выведет список наименований всех листов рабочей книги Excel по порядковому номеру их ярлычков, соответствующих их индексам.
Цикл для массива
Присвоим массиву список наименований животных и в цикле For Each… Next запишем их в переменную a. Информационное окно MsgBox выведет список наименований животных из переменной a.
Sub test3() Dim element As Variant, a As String, group As Variant group = Array(«бегемот», «слон», «кенгуру», «тигр», «мышь») ‘или можно присвоить массиву значения диапазона ячеек ‘рабочего листа, например, выбранного: group = Selection a = «Массив содержит следующие значения:» & vbNewLine For Each element In group a = a & vbNewLine & element Next MsgBox a End Sub |
Повторим ту же процедуру VBA, но всем элементам массива в цикле For Each… Next присвоим значение «Попугай». Информационное окно MsgBox выведет список наименований животных, состоящий только из попугаев, что доказывает возможность редактирования значений элементов массива в цикле For Each… Next.
Sub test4() Dim element As Variant, a As String, group As Variant group = Array(«бегемот», «слон», «кенгуру», «тигр», «мышь») ‘или можно присвоить массиву значения диапазона ячеек ‘рабочего листа, например, выделенного: group = Selection a = «Массив содержит следующие значения:» & vbNewLine For Each element In group element = «Попугай» a = a & vbNewLine & element Next MsgBox a End Sub |
Этот код, как и все остальные в этой статье, тестировался в Excel 2016.
Цикл для коллекции подкаталогов и выход из цикла
В этом примере мы будем добавлять в переменную a названия подкаталогов на диске C вашего компьютера. Когда цикл дойдет до папки Program Files, он добавит в переменную a ее название и сообщение: «Хватит, дальше читать не буду! С уважением, Ваш цикл For Each… Next.».
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Sub test5() Dim FSO As Object, myFolders As Object, myFolder As Object, a As String ‘Создаем новый FileSystemObject и присваиваем его переменной «FSO» Set FSO = CreateObject(«Scripting.FileSystemObject») ‘Извлекаем список подкаталогов на диске «C» и присваиваем ‘его переменной «myFolders» Set myFolders = FSO.GetFolder(«C:») a = «Папки на диске C:» & vbNewLine ‘Проходим циклом по списку подкаталогов и добавляем в переменную «a« ‘их имена, дойдя до папки «Program Files«, выходим из цикла For Each myFolder In myFolders.SubFolders a = a & vbNewLine & myFolder.Name If myFolder.Name = «Program Files» Then a = a & vbNewLine & vbNewLine & «Хватит, дальше читать не буду!» _ & vbNewLine & vbNewLine & «С уважением,» & vbNewLine & _ «Ваш цикл For Each... Next.« Exit For End If Next Set FSO = Nothing MsgBox a End Sub |
Информационное окно MsgBox выведет список наименований подкаталогов на диске C вашего компьютера до папки Program Files включительно и сообщение цикла о прекращении своей работы.
В результате работы программы будут выведены не только наименования подкаталогов, видимых при переходе в проводнике к диску C, но и скрытые и служебные папки. Для просмотра списка всех подкаталогов на диске C, закомментируйте участок кода от If до End If включительно и запустите выполнение процедуры в редакторе VBA Excel.
The art of Excel VBA programming is in the manipulation of properties of objects of Excel. The more skillfully you can play with these objects and properties, the more powerful the macros you can build.
The number one object in Excel you have to process is by far the Range object. In this article, I am going to walk you through the critical skills to loop through ranges in Excel worksheets.
Loop through cells in a range
The main skill to loop through a range is with FOR-NEXT loops. There are two FOR-NEXT loop conventions, which are both very useful when we loop through ranges. I would highly recommend to learn both skills.
Method 1: with a range variable
In the Range object, there are many Cell objects. We can therefore think of a Range as a group of Cells. We can effectively use the “For Each element In group” convention of the For-Next statement to loop through every Cell inside a Range.
The macro LoopCells1 loops through every cell in Range “A1:C5” and applies a sequential counter into the content of each cell.
Sub LoopCells1() Dim cell As Range Dim counter As Integer 'loop through each cell object element within a range For Each cell In Range("A1:C5").Cells counter = counter + 1 'denotes the nth cell cell.Value = counter Next End Sub
The result after running the macro looks like this:
Method 2: with a numeric variable
Most VBA users are more confident with the For-Next loop convention of:
For counter = start To end
This convention can also be used to loop through cells within a range. The macro “LoopCells2” demonstrates how to loop through each cell in range A1:C5 by referring to the index number of cells. The loop begins with the index number of 1 to the upper bound which is the total number of cells in the range.
Sub LoopCells2() Dim c As Long Dim counter As Integer 'loop through each cell within a range by calling the index number of the cells For c = 1 To Range("A1:C5").Cells.Count 'put the index number into cell Range("A1:C5").Cells(c).Value = c Next End Sub
The result after running the macro “LoopCells2” looks identical to the result of the previous macro “LoopCells1”.
Important note on numeric variable type
One limitation of this method is with the upper limit of the numeric variable being declared and used in the For-Next loop. There are a few points you need to bear in mind:
- Avoid declaring an Integer typing variable for this purpose because the number of cells in a worksheet is far more than 32,767.
- Declare a Long variable instead, so that the loop can process up to 2,147,483,648 cells, which serves most cases.
- Declaring a Double variable type won’t solve the limitation.
- In case your process exceeded the limit of even a long variable, you will have to restructure your For-Next loop to use the “For Each element In group” convention.
But even with such limitations, this is still a very useful method. It’s often used because, in most situations, the limits of the variable type won’t be reached.
Note on order of cells being processed
When using either of the two methods above, the cells in the range are being processed in the same sequence: from left to right, then from top to bottom. The picture below visualizes such sequence:
If you want the cells to be processed in a different order, you need to learn other strategies which will be explained in the next few sections.
Loop through rows or columns in a range
Sometimes we want to loop through each row in a range (from top to bottom). Similar to looping through cells, we can do it with both conventions of the For-Next statement, either with a range object variable or a numeric variable.
Method 1: with a range variable
Sub LoopRows1() Dim r As Range Dim MyString As String 'Loop through each row, and apply a yellow colow fill For Each r In Range("A1:C5").Rows r.Interior.ColorIndex = 6 Next End Sub
To loop through columns, we just need to change the first line of the For-Next loop to go through the columns instead. In the example below, we want to loop through each column in range A1:C5, and change the column heading to Proper Case (first letter of each word in capital).
Sub LoopColumn1() Dim c As Range Dim MyString As String 'Loop through each column and set first cell to Proper Case For Each c In Range("A1:C5").Columns c.Cells(1).Value = StrConv(c.Cells(1).Value, vbProperCase) Next End Sub
Method 2: with a numeric variable
In this example, we want to loop through every column in a data table. (See picture of our sample data below.) If a column contains numeric data, we set the NumberFormat to 2 decimal places.
'apply 0.00 number format to columns with numeric values Sub FormatNumericColumns() Dim c As Integer Dim MyString As String With Range("A1").CurrentRegion For c = 1 To .Columns.Count 'test 2nd cell of column for numeric value If IsNumeric(.Columns(c).Cells(2).Value) Then .Columns(c).NumberFormat = "0.00" End If Next End Sub
The result of the macro looks like the image below. The number format of the last 3 columns with numeric data has been set to 2 decimal places.
(The dates in the first column are not considered by the VBA IsNumeric function as numeric. Please read my other article all about IsNumeric for more detail on this topic.)
Advanced strategies
Deleting columns (or rows)
Here we want to write a macro to delete the three columns with headings with the word “delete” (the yellow columns). We can tackle this problem with a For-Next loop we learned in the sections above.
First Attempt:
We can try to loop through each column with the “For Each element In group” convention. The macro below looks simple and straight-forward enough, looping through each column (element) within the group of columns in range A1:C5.
Sub DeleteColmns1() Dim c As Range Dim x As Integer With Range("A1:E5") For Each c In .Columns If c.Cells(1).Value = "delete" Then c.Delete End If Next End With End Sub
The result of the macro looks like the picture below. The macro has failed to delete all the three columns.
Reminder: When looping through a range, if you want to apply structural change to the range, NEVER use the “For Each element In group” convention because it may create unexpected results. In some cases, (e.g. insert columns), it will even cause an infinite loop and your Excel may be frozen and you’ll have to force quit Excel and lose your unsaved work.
Second Attempt:
Now, how about using the “For counter = start To end” convention?
Sub DeleteColmns2() Dim tmp As Integer Dim x As Integer With Range("A1:E5") For x = 1 To .Columns.Count If .Columns(x).Cells(1).Value = "delete" Then .Columns(x).Delete End If Next End With End Sub
The result looks identical to that of the previous macro:
If we looked at the result more carefully, we noticed that the original 2nd and 4th column were deleted, but the original 3rd column was not. This was because when the 2nd column was deleted (when x=2), the 3rd column has become the 2nd column which has been skipped when the For-Next loop proceed to process x = 3.
Solution:
So, how do we tackle this problem? The answer is with the For-Next statement convention of “For counter = end To start step -1″, which processes the range from back to front (from the last column backward to the first column).
Sub DeleteColumnFinal() Dim x As Integer With Range("A1").CurrentRegion For x = .Columns.Count To 1 Step -1 If .Columns(x).Cells(1).Value = "delete" Then .Columns(x).Delete End If Next End With End Sub
Loop though every n-th row in a range
We have a data table, and we want to apply a yellow shading (fill) to the odd number rows. And we don’t want to shade the first row which contains the field headings.
Solution 1:
We can use the “For counter = start To end” convention to tackle this problem. We can loop through each row beginning from the 2nd row (which bypassed the field headings). If the row number is odd, we apply a yellow color.
'Shade alternate (even) rows of data Sub ShadeRows1() Dim r As Long With Range("A1").CurrentRegion For r = 1 To .Rows.Count If r / 2 = Int(r / 2) Then 'even rows .Rows(r).Interior.ColorIndex = 6 End If Next End With End Sub
To enhance the macro to shade every n-th row, simply change the 2 in line 5 to n. For example:
If r / 3 = Int(r / 3) Then 'every 3 rows
Solution 2:
We can also use the “For counter = start to end step 2” convention. In the macro “ShadeRows2”, the loop begins from the 2nd row and then the 4th row, then 6th row, etc.
'Shade alternate (odd) rows of data from the 3rd row Sub ShadeRows2() Dim r As Long With Range("A1").CurrentRegion 'begin from 2nd and shade every other row For r = 2 To .Rows.Count Step 2 .Rows(r).Interior.ColorIndex = 6 Next End With End Sub
To enhance the macro to shade every 3rd row, simple change the 2 in line 5 to 3. For example:
For r = 3 To .Rows.Count Step 3
Conclusion
We have gone through in detail the different approaches to loop through a range in VBA, including the pitfalls and a couple of special scenarios. These techniques can also be applied in combination or with other VBA techniques to achieve more powerful automation with worksheet ranges in your macros.
Home / VBA / Loop Through a Range using VBA (Columns, Row, and UsedRange)
To loop through a range in VBA, you need to use the “For Each Loop”. By using this loop, you can write a code where you tell VBA to go through each cell in the range, column, or row and perform a specific activity.
Sub vba_loop_range()
Dim iCell As Range
For Each iCell In Range("A1:A10").Cells
iCell.Value = "Yes"
Next iCell
End Sub
Following are steps for looping through a range:
- First, declare a variable to use as a cell of the range to loop.
- After that, start the “For Each loop” and use “iCell” variable to represent each cell in the range while the loop.
- Next, you need to write a line of code to perform some activity to each cell we are looping the range.
- In the end, end the code for a loop.
Loop Through Entire Column and a Row using VBA
In the same way, you can loop through each cell of a row using the following code that is just like the code we have used in the earlier example, the only difference is the range that we have specified.
Note: Before you loop through an entire column or a row you need to understand that it can take quite a time to complete the loop and it can make your Excel freeze for few minutes.
Sub vba_loop_range()
Dim iCell As Range
For Each iCell In Range("A:A").Cells
iCell.Value = "Yes"
Next iCell
End Sub
And in the same way, you can use a full row as a range to loop through.
Sub vba_loop_range()
Dim iCell As Range
For Each iCell In Range("1:1").Cells
iCell.Value = "Yes"
Next iCell
End Sub
Loop Through Dynamic Range
And if you want to loop through a dynamic range of cells refer to the following code.
Sub vba_dynamic_loop_range()
Dim iCell As Range
Dim iRange1 As String
Dim iRange2 As String
Dim rangeName As String
iRange1 = ActiveCell.Address
iRange2 = ActiveCell.Offset(5, 5).Address
rangeName = iRange1 & ":" & iRange2
For Each iCell In Range(rangeName).Cells
iCell = "Yes"
Next iCell
End Sub
Ranges are a key concept in Excel, and knowing how to work with them is essential for anyone who wants to program or automate their work using Excel VBA.
In this tutorial, we’ll take a look at how to work with Excel ranges in VBA. We’ll start by discussing what a Range object is. Then, we’ll look at the different ways of referencing a range. Lastly, we’ll explore various examples of how to work with ranges using VBA code.
Excel VBA: The Range object
The Excel VBA Range object is used to represent a range in a worksheet. A range can be a cell, a group of cells, or even all the 17,179,869,184 cells in a sheet.
When programming with Excel VBA, the Range object is going to be your best friend. That’s because much of your work will focus on manipulating data within sheets. Understanding how to work with the Range object will make it easier for you to perform various actions on cells, such as changing their values, sorting, or doing a copy-paste.
The following is the Excel object hierarchy:
Application > Workbook > Worksheet > Range
You can see that the Excel VBA Range object is a property of the Worksheet object. This means that you can access a range by specifying the name of the sheet and the cell address you want to work with. When you don’t specify a sheet name, by default Excel will look for the range in the active sheet. For example, if Sheet1 is active, then both of these lines will refer to the same cell range:
Range("A1") Worksheets("Sheet1").Range("A1")
Let’s have a closer look at how to reference a range in the section below.
Referencing a range of cells in Excel VBA
Referring to a Range object in Excel VBA can be done in several ways. We’ll discuss the basic syntax and some alternatives that you might want to use, depending on your needs.
Excel VBA: Syntax for specifying a cell range
To refer to a range that consists of one cell, for example, cell D5, you can use the syntax below:
Range("D5")
To refer to a range of cells, you have two acceptable syntaxes. For example, A1 through D5 can be specified using any one below:
Range("A1:D5") Range("A1", "D5")
To refer to a range outside the active sheet, you need to include the worksheet name. Here’s an example:
Worksheets("Sheet1").Range("A1:D5")
To refer to an entire row, for example, Row 5:
Range("5:5")
To refer to an entire column, for example, Column D:
Range("D:D")
Excel VBA also allows you to refer to multiple ranges at once by using a comma to separate each area. For example, see the below syntax used for referring to all ranges shown in the image:
Range("B2:D8, F4:G5")
Tip: Notice that all of the syntaxes above use double quotes to enclose the range address. To make it quicker for you to type, you can use shortcuts that involve using square brackets without quotes, as shown in the table below:
Syntax | Shortcut |
---|---|
Range("D5") |
[D5] |
Range("A1:D5") |
[A1:D5] |
Range("5:5") |
[5:5] |
Range("B2:D8, F4:G5") |
[B2:D8, F4:G5] |
Excel VBA: Referencing a named range
You have probably already used named ranges in your worksheets. They can be found under Name Manager in the Formulas tab.
To refer to a range named MyRange, use the following code:
Range("MyRange")
Remember to enclose the range’s name in double quotes. Otherwise, Excel thinks that you’re referring to a variable.
Alternatively, you can also use the shortcut syntax discussed previously. In this case, double quotes aren’t used:
[MyRange]
Excel VBA: Referencing a range using the Cells property
Another way to refer to a range is by using the Cells property. This property takes two arguments:
Cells(Row, Column)
You must use a numeric value for Row, but you may use either a numeric or string value for Column. Both of these lines refer to cell D5:
Cells(5, "D") Cells(5, 4)
The advantage of using the Cells property to refer to ranges becomes clear when you need to loop through rows or columns. You can create a more readable piece of code by using variables as the Cells arguments in a looping.
Excel VBA: Referencing a range using the Offset property
The Offset property provides another handy means for referring to ranges. It allows you to refer to a cell based on the location of another cell, such as the active cell.
Like the Cells property, the Offset property has two parameters. The first determines how many rows to offset, while the second represents the number of columns to offset. Here is the syntax:
Range.Offset(RowOffset, ColumnOffset)
For example, the following code refers to cell D5 from cell A1:
Range("A1").Offset(4,3)
The negative numbers refer to cells that are above or below the range of values. For example, a -2 row offset refers to two rows above the range, and a -1 column offset refers to a column to the left of the range. The following example refers to cell A1:
Range("D3").Offset(-2, -3)
If you need to go over only a row or a column, but not both, you don’t have to enter both the row and the column parameters. You can also use 0 as one or both of the arguments. For example, the following lines refer to D5:
Range("D5").Offset(0, 0) Range("D2").Offset(3, 0) Range("G5").Offset(, -3)
Let’s take a look at some of the most common range examples. These examples will show you how to use VBA to select and manipulate ranges in your worksheets. Some of these examples are complete procedures, while others are code snippets that you can just copy-paste to your own Sub to try.
Excel VBA: Select a range of cells
To select a range of cells, use the Select method.
The following line selects a range from A1 to D5 in the active worksheet:
Range("A1:D5").Select
To select a range from A1 to the active cell, use the following line:
Range("A1", ActiveCell).Select
The following code selects from the active cell to 3 rows below the active cell and five columns to the right:
Range(ActiveCell, ActiveCell.Offset(3, 5)).Select
It’s important to note that when you need to select a range on a specific worksheet, you need to ensure that the correct worksheet is active. Otherwise, an error will occur. For example, you want to select B2 to J5 on Sheet1. The following code will generate an error if Sheet1 is not active:
Worksheets("Sheet1").Range("B2:J5").Select
Instead, use these two lines of code to make your code work as expected:
Worksheets("Sheet1").Activate Range("B2:J5").Select
Excel VBA: Set values to a range
The following statement sets a value of 100 into cell C7 of the active worksheet:
Range("C7").Value = 100
The Value property allows you to represent the value of any cell in a worksheet. It’s a read/write property, so you can use it for both reading and changing values.
You can also set values of a range of any size. The following statement enters the text “Hello” into each cell in the range A1:C7 in Sheet2:
Worksheets("Sheet2").Range("A1:C7").Value = "Hello"
Value is the default property for a Range object. This means that if you don’t provide any properties in your range, Excel will use this Value property.
Both of the following lines enter a value of 100 into cell C7 of the active worksheet:
Range("C7").Value = 100 Range("C7") = 100
Excel VBA: Copy range to another sheet
To copy and paste a range in Excel VBA, you use the Copy and Paste methods. The Copy method copies a range, and the Paste method pastes it into a worksheet. It might look a bit complicated but let’s see what each does with an example below.
Let’s say you have Orders data, as shown in the below screenshot, which is imported from Airtable every day using Coupler.io. This tool allows users to do it automatically on the schedule they want with just a few clicks and no coding required.
In addition, they can combine data from other different sources (such as Jira, Mailchimp, etc.) into one destination for analysis purposes.
As you can see, the data starts from B2. You want to copy only range B2:C11 and paste them to Sheet2 at the same address. The following is an example Sub you can use:
Sub CopyRangeToAnotherSheet() Sheets("Sheet1").Activate Range("B2:C11").Select Selection.Copy Sheets("Sheet2").Activate Range("B2").Select ActiveSheet.Paste End Sub
Alternatively, you can also use a single line of code as shown below:
Sub CopyRangeToAnotherSheet2() Worksheets("Sheet1").Range("B2:C11").Copy Worksheets("Sheet2").Range("B2") End Sub
The above Sub procedure takes advantage of the fact that the Copy method can use an argument that corresponds to the destination range for the copy operation. Notice that actually, you don’t have to select a range before doing something with it.
Excel VBA: Dynamic range example
In many cases, you may need to copy a range of cells but don’t know exactly how many rows and columns it has. For example, if you use Coupler.io or other integration tools to import data from an external app into Excel on a daily schedule, the number of rows may change over time.
How can you determine this dynamic range? One solution is to use the CurrentRegion property. This property returns an Excel VBA Range object within its boundaries. As long as the data is surrounded by one empty row and one empty column, you can select it with CurrentRegion.
The following line selects the contiguous range around Cell B2:
Range("B2").CurrentRegion.Select
Now, let’s say you want to select only Columns B and C of the range, and from the second row, you can use the following line:
Range("B2", Range("C2").End(xlDown)).Select
You can now do whatever you want with your selected range — copy or move it to another sheet, format it, and so on.
If you want to find the last row of a used range using Excel VBA, it’s also possible without selecting anything. Here’s the line you can use to find the row number of Column B’s last row data:
' Find the row number of Column B's last row data RowNumOfLastRow = Cells(Rows.Count, 2).End(xlUp).Row ' Result: 11 MsgBox RowNumOfLastRow
Excel VBA: Loop for each cell in a range
For looping each cell in a range, the For Each loop is an excellent choice. This type of loop is great for looping through a collection of objects such as cells in a range, worksheets in a workbook, or other collections.
The following procedure shows how to loop through each cell in Range B2:K11. We use an object variable named Obj, which refers to the cell being processed. Within the loop, the code checks if the cell contains a formula and then sets its color to blue.
Sub LoopForEachCell() Dim obj As Range For Each obj In Range("B2:K11") If obj.HasFormula Then obj.Font.Color = vbBlue Next obj End Sub
Excel VBA: Loop for each row in a range
When looping through rows (or columns), you can use the Cells property to refer to a range of cells. This makes your code more readable compared to when you’re using the Range syntax.
For example, to loop for each row in range B2:K11 and bold all the cells from Column I to K, you might write a loop like this:
Sub LoopForEachRow() For i = 1 To 11 Range("I" & i & ":K" & i).Font.Bold = True Next i End Sub
Instead of typing in a range address, you can use the Cells property to make the loop easier to read and write. For example, the code below uses the Cells and Resize properties to find the required cell based on the active cell:
Sub LoopForEachRow2() For i = 1 To 11 Cells(i, "I").Resize(, 3).Font.Bold = True Next i End Sub
Excel VBA: Clear a range
There are three ways to clear a range in Excel VBA.
The first is to use the Clear method, which will clear the entire range, including cell contents and formatting.
The second is to use the ClearContents method, which will clear the contents of the range but leave the formatting intact.
The third is to use the ClearFormats method, which will clear the formatting of the range but leave the contents intact.
For example, to clear a range B1 to M15, you can use one of the following lines of code below, based on your needs:
Range("B1:M15").Clear Range("B1:M15").ClearContents Range("B1:M15").ClearFormats
Excel VBA: Delete a range
When deleting a range, it differs from just clearing a range. That’s because Excel shifts the remaining cells around to fill up your deleted range.
The code below deletes Row 5 using the Delete method:
Range("5:5").Delete
To delete a range that is not a complete row or column, you have to provide an argument (such as xlToLeft, xlUp — based on your needs) that indicates how Excel should shift the remaining cells.
For example, the following code deletes cell B2 to M10, then fills the resulting gap by shifting the other cells to the left:
Range("B2:M10").Delete xlToLeft
Excel VBA: Delete rows with a specific condition in a range
You can also use a VBA code to delete rows with a specific condition. For example, let’s try to delete all the rows with a discount of 0 from the below sheet:
Here’s an example Sub you may want to use:
Sub DeleteWithCondition() For i = 3 To 11 If Cells(i, "F").Value = 0 Then Cells(i, 1).EntireRow.Delete End If Next i End Sub
The above code loops from Row 3 to 11. In each loop, it checks the discount value in Column F and removes the entire row if the value equals 0.
Excel VBA: Find values in a range
With the below data, suppose you want to find if there is an order with OrderNumber equal to 1003320 and output its cell address.
You can use the Find method in this case, as shown in the below code:
Sub FindOrder() Dim Rng As Range Set Rng = Range("B3:B11").Find("1003320") If Rng Is Nothing Then MsgBox "The OrderNumber not found." Else MsgBox Rng.Address End If End Sub
The output of the above code will be the first occurrence of the search value in the specified range. If the value is not found, a message box showing info that the order is not found will appear.
Excel VBA: Add alрhаbеtѕ using Rаngе .Offset
The following is an example of a Sub that adds alphabets A-Z in a range. The code uses Offset to refer to a cell below the active cell in a loop.
Sub AddAlphabetsAZ() Dim i As Integer ' Use 97 To 122 for lowercase letters For i = 65 To 90 ActiveCell.Value = Chr(i) ActiveCell.Offset(1, 0).Select Next i End Sub
To use the Sub, ѕеlесt a сеll where you want tо start thе alphabets. Then, run it by pressing F5. The code will insert A-Z to the cells downward.
Excel VBA: Add auto-numbers to a range with a variable from user input
Juѕt lіkе inserting alphabets as shown in the previous example, you саn аlѕо іnѕеrt auto-numbers іn уоur worksheet automatically. This can be helpful when you work with large data.
The following is an example of a Sub that adds auto-numbers to your Excel sheet:
Sub AddAutoNumbers() Dim i As Integer On Error GoTo ErrorHandler i = InputBox("Enter the maximum number: ", "Enter a value") For i = 1 To i ActiveCell.Value = i ActiveCell.Offset(1, 0).Select Next i ErrorHandler: Exit Sub End Sub
Tо uѕе the соdе, уоu need tо ѕеlесt the сеll frоm where you want tо start thе auto-numbеrѕ. Then, run the Sub. In the message box that appears, enter the maximum value for the auto-numbers and сlісk OK.
Excel VBA: Sum a range
Imagine that you have written a Sub procedure to import Orders.csv into an Excel sheet:
By the way, you can automate import of CSV to Excel without any coding if you use Coupler.io
You want to sum up all the discount values and put the result in J12. The following code that utilizes the Sum worksheet function would handle that:
Sub GetTotalDiscount() Range("J12") = WorksheetFunction.Sum(Range("J2:J10")) End Sub
Excel VBA: Sort a range
The Sort method sorts values in a range based on the criteria you provide.
Suppose you have the following sheet:
To sort the above data based оn thе vаluеѕ іn Column D, you can use the following code:
Sub SortBySingleColumn() Range("A1:E10").Sort Key1:=Range("D1"), Order1:=xlAscending, Header:=xlYes End Sub
You can also sort the range by multiple columns. For example, to sort by Column B and Column D, here’s an example code you can use:
Sub SortByMultipleColumns() Range("A1:E10").Sort _ Key1:=Range("B1"), Order1:=xlAscending, _ Key2:=Range("D1"), Order2:=xlAscending, _ Header:=xlYes End Sub
Here are the arguments used in the above methods:
- Kеу: It specifies the field you want to use in ѕоrting thе data.
- Ordеr: It ѕресіfies whеthеr уоu wаnt tо sort the dаtа іn аѕсеndіng or dеѕсеndіng order.
- Header: It spесіfies whеthеr уоur data hаѕ hеаdеrѕ оr nоt.
Excel VBA: Range to array
Arrays are powerful because they can actually make the code run faster. Especially when working with large data, you can use arrays to make all the processing happen in memory and then write the data to the sheet once.
For example, suppose you have the following sheet:
The following Sub uses a variable X, which is a Variant data type, to store the value of Range A2:E10. Variants can hold any type of data, including arrays.
Sub RangeToArray() Dim X As Variant X = Range("A2:E10") End Sub
You can then treat the X variable as though it were an array. The following line returns the value of cell A6:
MsgBox X(5, 1) ' Result: 1003320
Now, let’s say you want to calculate the total order using the following calculation:
Quantity * Price - Discount
Rather than doing calculation and writing the result for each row using a looping, you can store the calculation result in an array OrderTotal as shown in the below code and write the result once:
Sub CalculateTotalOrder() Dim X As Variant, OrderTotal As Variant X = Range("A2:E10") ReDim OrderTotal(UBound(X)) For i = LBound(X) To UBound(X) OrderTotal(i - 1) = X(i, 3) * X(i, 4) - X(i, 5) Next i Range("F1") = "OrderTotal" Range("F2").Resize(UBound(OrderTotal)) = _ Application.Transpose(OrderTotal) End Sub
Here’s the final result:
Subscript out of range: Excel VBA Runtime error 9
This error message often happens when you try to access a range of cells in a worksheet that has been deleted or renamed.
Let’s say your code expected a worksheet named Setting. For some reason, this sheet is renamed Settings. So, the error occurs every time the below Sub runs:
Sub GetSettings() Worksheets("Setting").Select x = Range("A1").Value End Sub
To prevent the runtime error happening again, you may want to add an error handler code like this below:
Sub GetSettings() On Error Resume Next ws = Worksheets("Setting") Name = ws.Name If Not Err.Number = 0 Then MsgBox "Expected to find a Setting worksheet, but it is missing." Exit Sub End If On Error GoTo 0 ws.Select x = Range("A1").Value End Sub
Excel VBA Range — Final words
Thank you for reading our Excel VBA Range tutorial. We hope that you’ve found it helpful! And if there’s anything else about Excel programming or other topics that interest you, be sure to check out our other Excel tutorials.
In addition, you may find that Coupler.io is a valuable tool for you if you’re looking for an easy way to pull and combine your data from multiple sources into one destination for analysis and reporting. This tool also lets you specify the range address of your imported data so you can keep all of your calculations (including. formulas) in the sheets.
Thanks again for reading, and happy coding!
-
Senior analyst programmer
Back to Blog
Focus on your business
goals while we take care of your data!
Try Coupler.io
In this Article
- VBA Loop Quick Examples
- For Each Loops
- For Next Loops
- Do While Loops
- Do Until Loops
- VBA Loop Builder
- VBA For Next Loop
- For Loop Syntax
- For Loop Step
- For Loop Step – Inverse
- Nested For Loop
- Exit For
- Continue For
- VBA For Each Loop
- For Each Cell in Range
- For Each Worksheet in Workbook
- For Each Open Workbook
- For Each Shape in Worksheet
- For Each Shape in Each Worksheet in Workbook
- For Each – IF Loop
- VBA Do While Loop
- Do While
- Loop While
- VBA Do Until Loop
- Do Until
- Loop Until
- Exit Do Loop
- End or Break Loop
- More Loop Examples
- Loop Through Rows
- Loop Through Columns
- Loop Through Files in a Folder
- Loop Through Array
- Loops in Access VBA
To work effectively in VBA, you must understand Loops.
Loops allow you to repeat a code block a set number of times or repeat a code block on a each object in a set of objects.
First we will show you a few examples to show you what loops are capable of. Then we will teach you everything about loops.
VBA Loop Quick Examples
For Each Loops
For Each Loops loop through every object in a collection, such as every worksheet in workbook or every cell in a range.
Loop Through all Worksheets in Workbook
This code will loop through all worksheets in the workbook, unhiding each sheet:
Sub LoopThroughSheets()
Dim ws As Worksheet
For Each ws In Worksheets
ws.Visible = True
Next
End Sub
Loop Through All Cells in Range
This code will loop through a range of cells, testing if the cell value is negative, positive, or zero:
Sub If_Loop()
Dim Cell as Range
For Each Cell In Range("A2:A6")
If Cell.Value > 0 Then
Cell.Offset(0, 1).Value = "Positive"
ElseIf Cell.Value < 0 Then
Cell.Offset(0, 1).Value = "Negative"
Else
Cell.Offset(0, 1).Value = "Zero"
End If
Next Cell
End Sub
For Next Loops
Another type of “For” Loop is the For Next Loop. The For Next Loop allows you to loop through integers.
This code will loop through integers 1 through 10, displaying each with a message box:
Sub ForLoop()
Dim i As Integer
For i = 1 To 10
MsgBox i
Next i
End Sub
Do While Loops
Do While Loops will loop while a condition is met. This code will also loop through integers 1 through 10, displaying each with a message box.
Sub DoWhileLoop()
Dim n As Integer
n = 1
Do While n < 11
MsgBox n
n = n + 1
Loop
End Sub
Do Until Loops
Conversely, Do Until Loops will loop until a condition is met. This code does the same thing as the previous two examples.
Sub DoUntilLoop()
Dim n As Integer
n = 1
Do Until n >= 10
MsgBox n
n = n + 1
Loop
End Sub
We will discuss this below, but you need to be extremely careful when creating Do While or Do Until loops so that you don’t create a never ending loop.
VBA Loop Builder
This is a screenshot of the “Loop Builder” from our Premium VBA Add-in: AutoMacro. The Loop Builder allows you to quickly and easily build loops to loop through different objects, or numbers. You can perform actions on each object and/or select only objects that meet certain criteria.
The add-in also contains many other code builders, an extensive VBA code library, and an assortment of coding tools. It’s a must have for any VBA developer.
Now we will cover the different types of loops in depth.
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More
VBA For Next Loop
For Loop Syntax
The For Next Loop allows you to repeat a block of code a specified number of times. The syntax is:
[Dim Counter as Integer]
For Counter = Start to End [Step Value]
[Do Something]
Next [Counter]
Where the items in brackets are optional.
- [Dim Counter as Long] – Declares the counter variable. Required if Option Explicit is declared at the top of your module.
- Counter – An integer variable used to count
- Start – The start value (Ex. 1)
- End – The end value (Ex. 10)
- [Step Value] – Allows you to count every n integers instead of every 1 integer. You can also go in reverse with a negative value (ex. Step -1)
- [Do Something] – The code that will repeat
- Next [Counter] – Closing statement to the For Next Loop. You can include the Counter or not. However, I strongly recommend including the counter as it makes your code easier to read.
If that’s confusing, don’t worry. We will review some examples:
Count to 10
This code will count to 10 using a For-Next Loop:
Sub ForEach_CountTo10()
Dim n As Integer
For n = 1 To 10
MsgBox n
Next n
End Sub
For Loop Step
Count to 10 – Only Even Numbers
This code will count to 10 only counting even numbers:
Sub ForEach_CountTo10_Even()
Dim n As Integer
For n = 2 To 10 Step 2
MsgBox n
Next n
End Sub
Notice we added “Step 2”. This tells the For Loop to “step” through the counter by 2. We can also use a negative step value to step in reverse:
VBA Programming | Code Generator does work for you!
For Loop Step – Inverse
Countdown from 10
This code will countdown from 10:
Sub ForEach_Countdown_Inverse()
Dim n As Integer
For n = 10 To 1 Step -1
MsgBox n
Next n
MsgBox "Lift Off"
End Sub
Delete Rows if Cell is Blank
I’ve most frequently used a negative step For-Loop to loop through ranges of cells, deleting rows that meet certain criteria. If you loop from the top rows to the bottom rows, as you delete rows you will mess up your counter.
This example will delete rows with blank cells (starting from the bottom row):
Sub ForEach_DeleteRows_BlankCells()
Dim n As Integer
For n = 10 To 1 Step -1
If Range("a" & n).Value = "" Then
Range("a" & n).EntireRow.Delete
End If
Next n
End Sub
Nested For Loop
You can “nest” one For Loop inside another For Loop. We will use Nested For Loops to create a multiplication table:
Sub Nested_ForEach_MultiplicationTable()
Dim row As Integer, col As Integer
For row = 1 To 9
For col = 1 To 9
Cells(row + 1, col + 1).Value = row * col
Next col
Next row
End Sub
Exit For
The Exit For statement allows you to exit a For Next loop immediately.
You would usually use Exit For along with an If Statement, exiting the For Next Loop if a certain condition is met.
For example, you might use a For Loop to find a cell. Once that cell is found, you can exit the loop to speed up your code.
This code will loop through rows 1 to 1000, looking for “error” in column A. If it’s found, the code will select the cell, alert you to the found error, and exit the loop:
Sub ExitFor_Loop()
Dim i As Integer
For i = 1 To 1000
If Range("A" & i).Value = "error" Then
Range("A" & i).Select
MsgBox "Error Found"
Exit For
End If
Next i
End Sub
Important: In the case of Nested For Loops, Exit For only exits the current For Loop, not all active Loops.
Continue For
VBA does not have the “Continue” command that’s found in Visual Basic. Instead, you will need to use “Exit”.
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
VBA For Each Loop
The VBA For Each Loop will loop through all objects in a collection:
- All cells in a range
- All worksheets in a workbook
- All shapes in a worksheet
- All open workbooks
You can also use Nested For Each Loops to:
- All cells in a range on all worksheets
- All shapes on all worksheets
- All sheets in all open workbooks
- and so on…
The syntax is:
For Each Object in Collection
[Do Something]
Next [Object]
Where:
- Object – Variable representing a Range, Worksheet, Workbook, Shape, etc. (ex. rng)
- Collection – Collection of objects (ex. Range(“a1:a10”)
- [Do Something] – Code block to run on each object
- Next [Object] – Closing statement. [Object] is optional, however strongly recommended.
For Each Cell in Range
This code will loop through each cell in a range:
Sub ForEachCell_inRange()
Dim cell As Range
For Each cell In Range("a1:a10")
cell.Value = cell.Offset(0,1).Value
Next cell
End Sub
For Each Worksheet in Workbook
This code will loop through all worksheets in a workbook, unprotecting each sheet:
Sub ForEachSheet_inWorkbook()
Dim ws As Worksheet
For Each ws In Worksheets
ws.Unprotect "password"
Next ws
End Sub
For Each Open Workbook
This code will save and close all open workbooks:
Sub ForEachWB_inWorkbooks()
Dim wb As Workbook
For Each wb In Workbooks
wb.Close SaveChanges:=True
Next wb
End Sub
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
For Each Shape in Worksheet
This code will delete all shapes in the active sheet.
Sub ForEachShape()
Dim shp As Shape
For Each shp In ActiveSheet.Shapes
shp.Delete
Next shp
End Sub
For Each Shape in Each Worksheet in Workbook
You can also nest For Each Loops. Here we will loop through all shapes in all worksheets in the active workbook:
Sub ForEachShape_inAllWorksheets()
Dim shp As Shape, ws As Worksheet
For Each ws In Worksheets
For Each shp In ws.Shapes
shp.Delete
Next shp
Next ws
End Sub
For Each – IF Loop
As we’ve mentioned before, you can use an If statement within a loop, performing actions only if certain criteria is met.
This code will hide all blank rows in a range:
Sub ForEachCell_inRange()
Dim cell As Range
For Each cell In Range("a1:a10")
If cell.Value = "" Then _
cell.EntireRow.Hidden = True
Next cell
End Sub
VBA Do While Loop
The VBA Do While and Do Until (see next section) are very similar. They will repeat a loop while (or until) a condition is met.
The Do While Loop will repeat a loop while a condition is met.
Here is the Do While Syntax:
Do While Condition
[Do Something]
Loop
Where:
- Condition – The condition to test
- [Do Something] – The code block to repeat
You can also set up a Do While loop with the Condition at the end of the loop:
Do
[Do Something]
Loop While Condition
We will demo each one and show how they differ:
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
Do While
Here is the Do While loop example we demonstrated previously:
Sub DoWhileLoop()
Dim n As Integer
n = 1
Do While n < 11
MsgBox n
n = n + 1
Loop
End Sub
Loop While
Now let’s run the same procedure, except we will move the condition to the end of the loop:
Sub DoLoopWhile()
Dim n As Integer
n = 1
Do
MsgBox n
n = n + 1
Loop While n < 11
End Sub
VBA Do Until Loop
Do Until Loops will repeat a loop until a certain condition is met. The syntax is essentially the same as the Do While loops:
Do Until Condition
[Do Something]
Loop
and similarly the condition can go at the start or the end of the loop:
Do
[Do Something]
Loop Until Condition
Do Until
This do Until loop will count to 10, like our previous examples
Sub DoUntilLoop()
Dim n As Integer
n = 1
Do Until n > 10
MsgBox n
n = n + 1
Loop
End Sub
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
Loop Until
This Loop Until loop will count to 10:
Sub DoLoopUntil()
Dim n As Integer
n = 1
Do
MsgBox n
n = n + 1
Loop Until n > 10
End Sub
Exit Do Loop
Similar to using Exit For to exit a For Loop, you use the Exit Do command to exit a Do Loop immediately
Exit Do
Here is an example of Exit Do:
Sub ExitDo_Loop()
Dim i As Integer
i = 1
Do Until i > 1000
If Range("A" & i).Value = "error" Then
Range("A" & i).Select
MsgBox "Error Found"
Exit Do
End If
i = i + 1
Loop
End Sub
End or Break Loop
As we mentioned above, you can use the Exit For or Exit Do to exit loops:
Exit For
Exit Do
However, these commands must be added to your code before you run your loop.
If you are trying to “break” a loop that’s currently running, you can try pressing ESC or CTRL + Pause Break on the keyboard. However, this may not work. If it doesn’t work, you’ll need to wait for your loop to end or, in the case of an endless loop, use CTRL + ALT + Delete to force close Excel.
This is why I try to avoid Do loops, it’s easier to accidentally create an endless loop forcing you to restart Excel, potentially losing your work.
More Loop Examples
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
Loop Through Rows
This will loop through all the rows in a column:
Public Sub LoopThroughRows()
Dim cell As Range
For Each cell In Range("A:A")
If cell.value <> "" Then MsgBox cell.address & ": " & cell.Value
Next cell
End Sub
Loop Through Columns
This will loop through all columns in a row:
Public Sub LoopThroughColumns()
Dim cell As Range
For Each cell In Range("1:1")
If cell.Value <> "" Then MsgBox cell.Address & ": " & cell.Value
Next cell
End Sub
Loop Through Files in a Folder
This code will loop through all files in a folder, creating a list:
Sub LoopThroughFiles ()
Dim oFSO As Object
Dim oFolder As Object
Dim oFile As Object
Dim i As Integer
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder("C:Demo)
i = 2
For Each oFile In oFolder.Files
Range("A" & i).value = oFile.Name
i = i + 1
Next oFile
End Sub
Loop Through Array
This code will loop through the array ‘arrList’:
For i = LBound(arrList) To UBound(arrList)
MsgBox arrList(i)
Next i
The LBound function gets the “lower bound” of the array and UBound gets the “upper bound”.
Loops in Access VBA
Most of the examples above will also work in Access VBA. However, in Access, we loop through the Recordset Object rather than the Range Object.
Sub LoopThroughRecords()
On Error Resume Next
Dim dbs As Database
Dim rst As Recordset
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("tblClients", dbOpenDynaset)
With rst
.MoveLast
.MoveFirst
Do Until .EOF = True
MsgBox (rst.Fields("ClientName"))
.MoveNext
Loop
End With
rst.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
In this article, I offer two different ways to loop through rows of a table or range in Excel VBA. Looping through rows is a common task in VBA so it’s good to have a strong grasp of the code.
To start off, I have chosen to work with a file that has names, addresses, and unformatted phone numbers. A preview of the data is below.
I have also added a function to do the transformation from unformatted to formatted phone number. The function is below.
Function FormatAsPhoneNumber(n As String) As String 'takes a string with 10 digits and adds parens and dash FormatAsPhoneNumber = "(" & Left(n, 3) & ") " & Mid(n, 4, 3) & "-" & Right(n, 4) End Function
Looping Through Rows with a For Each Loop
Sub FormatAsPhoneNumbersForEachLoop() Dim table As Range ' table is the range I want to loop through rows. Other ways to get such a range may be to use a named range or static range. ' This method depends on having at least one row in table and no blank rows. Set table = Range("A2", Range("A2").End(xlToRight).End(xlDown)) ' loop through each row in table, with row as a range For Each Row In table.Rows ' format the value in the third column as a phone number ' note that it is always selecting the first row because the range is restricted to the current row Row.Cells(1, 3).Value = FormatAsPhoneNumber(Row.Cells(1, 3).Value) Next Row End Sub
The code above uses a for each loop, rather than a standard for loop, to loop through the rows. The variable Row in the For Each loop is a range representing a row. One advantage of this is that there is no need to select within the larger range. It’s also great where you wish to do something to the entire row at once, for example, a formatting operation. For this application however, I find it a bit clunky. Let’s look at using a standard For loop.
Looping Through Rows with a For Loop.
Sub FormatAsPhoneNumbersForLoop() Dim table As Range ' table is the range I want to loop through rows. Other ways to get such a range may be to use a named range or static range. ' This method depends on having at least one row in table and no blank rows. Set table = Range("A2", Range("A2").End(xlToRight).End(xlDown)) ' loop through each row in table, using i to keep track of row For i = 1 To table.Rows.Count ' format the value in the third column as a phone number table(i, 3).Value = FormatAsPhoneNumber(table(i, 3).Value) Next i End Sub
In the above example, a standard For loop is used to loop through the range. Rather than receiving the row as a new range within the body of the loop, a counter is used which allows the row to be selected from the broader range. Overall, I personally prefer this application for operations like this where you wish to loop through each row and target a certain cell.
Conclusion
That’s two methods to loop through rows in a range or table! If you have any comments please comment below.
This post provides a complete guide to the standard VBA For Loop and the VBA For Each Loop.
If you are looking for information about the VBA While and VBA Do Loop then go here.
If you want some quick info about the For loops then check out the Quick Guide table in the section below.
If you are looking for information on a particular topic then check out the Table of Contents below.
“History is about loops and continuums” – Mike Bidlo.
Related Links for the VBA For Loop
The Complete Guide to Ranges in Excel VBA.
The Complete Guide to Copying Data in Excel VBA.
VBA Do While Loop.
A Quick Guide to the VBA For Loop
Loop format | Description | Example |
---|---|---|
For … Next | Run 10 times | For i = 1 To 10 Next |
For … Next | Run 5 times. i=2,4, 6 etc. | For i = 2 To 10 Step 2 Next |
For … Next | Run in reverse order | For i = 10 To 1 Step -1 Debug.Print i Next |
For … Next | Go through Collection | For i = 1 To coll.Count Debug.Print coll(i) Next |
For … Next | Go through array | For i = LBound(arr) To UBound(arr) Debug.Print arr(i) Next i |
For … Next | Go through 2D array | For i = LBound(arr) To UBound(arr) For j = LBound(arr,2) To UBound(arr,2) Debug.Print arr(i, j) Next j Next i |
For Each … Next | Go through Collection | Dim item As Variant For Each item In coll Debug.Print item Next item |
For Each … Next | Go through array | Dim item As Variant For Each item In arr Debug.Print item Next item |
For Each … Next | Go through 2D array | Dim item As Variant For Each item In arr Debug.Print item Next item |
For Each … Next | Go through Dictionary | Dim key As Variant For Each key In dict.Keys Debug.Print key, dict(key) Next key |
Both types | Exit Loop | For i = 1 To 10 If Cells(i,1) = «found» Then Exit For End If Next i |
The VBA For Loop Webinar
If you are a member of the website, click on the image below to view the webinar for this post.
(Note: Website members have access to the full webinar archive.)
Introduction to the VBA For Loop
Loops are by far the most powerful component of VBA. They are the rocket fuel of your Macros. They can perform tasks in milliseconds that would take humans hours. They also dramatically reduce the lines of code your applications need.
For Loops have been part of all major programming languages since they were first used with Fortan in 1957.
If you have never used loops before then this post is a great place to start. It provides an in-depth guide to loops, written in plain English without the jargon.
Let’s start with a very important question – what are loops and why do we need them?
What are VBA For Loops?
A loop is simply a way of running the same lines of code a number of times. Obviously running the same code over and over would give the same result.
So what is important to understand is that the lines of code normally contain a variable that changes slightly each time the loop runs.
For example, a loop could write to cell A1, then cell A2, A3 and so on. The slight change each time is the row.
Let’s look at a simple example.
VBA For Loop Example 1
The following code prints the values 1 to 5 in the Immediate Window(Ctrl + G to view).
Debug.Print 1 Debug.Print 2 Debug.Print 3 Debug.Print 4 Debug.Print 5
The Immediate Window
If you have not used the Immediate Window before then this section will get you up to speed quickly.
The function Debug.Print writes values to the Immediate Window. To view this window select View->Immediate Window from the menu( the shortcut is Ctrl + G)
VBA For Loop Example 2
Now imagine we want to print out the numbers 1 to 20. We would need to add 15 more lines to the example above.
However, using a loop we only need to write Debug.Print once.
For i = 1 To 20 Debug.Print i Next i
The output is:
Output
If we needed print the numbers 1 to 1000 then we only need to change the 20 to 1000.
Normally when we write code we would use a variable instead of a number like 20 or 1000. This gives you greater flexibility. It allows you to decide the number of times you wish to run the loop when the code is running. The following example explains this.
VBA For Loop Example 3
A common task in Excel is read all the rows with with data.
The way you approach this task is as follows
- Find the last row with data
- Store the value in variable
- Use the variable to determine how many times the loop runs
Using a variable in the loop makes your code very flexible. Your will work no matter how many rows there are.
Let’s have a look at an example. Imagine you receive a sheet with a list of fruit types and their daily sales. You want to count the number of Oranges sold and this list will vary in size depending on sales.
The following screenshot shows an example of this list
Sample Data of Fruit Sales
We can use the code to count the oranges
' https://excelmacromastery.com/ Sub CountFruit() ' Get the last row with text Dim LastRow As Long LastRow = Sheet1.Cells(Sheet1.Rows.Count, 1).End(xlUp).Row Dim i As Long, Total As Long ' Use LastRow in loop For i = 2 To LastRow ' Check if cell has text "Orange" If Sheet1.Cells(i, 1).Value = "Oranges" Then ' Add value in column B to total Total = Total + Sheet1.Cells(i, 2).Value End If Next i ' Print total Debug.Print "Total oranges sold was:"; Total End Sub
You can try this code for yourself. Change the number of fruit items and you will see that the code still works fine.
If you were to increase the number fruit items to a large value like 10,000 then you will hardly notice the difference in the time it takes to run – almost instantly.
Loops are super fast. This is what makes them so powerful. Imagine performing a manual task on 10,000 cells. It would take a considerable amount of time.
Advantages of the VBA For Loop
4To conclude this section we will list the major advantages of using loops
- They reduce the lines code you need
- They are flexible
- They are fast
In the next sections we will look at the different types of loops and how to use them.
The Standard VBA For Loop
The VBA For loop is the most common loop you will use in Excel VBA. The For Loop is used when you can determine the number of times it will be run. For example, if you want to repeat something twenty times.
YouTube Video For Loop
Check out this YouTube Video of the For Loop:
Get the workbook and code for this video here
Format of the Standard VBA For Loop
The Standard VBA For Loop has the following format:
For <variable> = <start value> to <end value>
Next <variable>
The start and end values can be variables. Also the variable after Next is optional but it is useful and it makes it clear which for loop it belongs to.
How a For Loop Works
Let’s look at a simple for loop that prints the numbers 1 to 3
Dim i As Long For i = 1 To 3 Debug.Print i Next i
How this code works is as follows
i is set to 1
The value of i(now 1) is printed
i is set to 2
The value of i(now 2) is printed
i is set to 3
The value of i(now 3) is printed
If we did not use a loop then the equivalent code would be
Dim i As Long i = i + 1 Debug.Print i i = i + 1 Debug.Print i i = i + 1 Debug.Print i
The i = i + 1 line is used to add 1 to i and is a common way in programming to update a counter.
Using Step with the VBA For Loop
You can see that i is increased by one each time. This is the default. You can specify this interval using Step keyword.
The next example shows you how to do this:
' Prints the even numbers i.e. 2,4,6,8 ... 20 For i = 2 To 20 Step 2 Debug.Print i Next i
You can use a negative number with Step which will count in reverse
' Prints the even numbers in reverse i.e. 20,18,16,14 ... 2 For i = 20 To 2 Step -2 Debug.Print i Next i
Note: if Step is positive then your starting number must be lower than you ending number. The following loop will not run because the starting number 20 is greater than 10. VBA therefore, thinks it has already reached the target value 10.
' Will not run as starting number already greater than 10 For i = 20 To 10 Step 1 Debug.Print i Next i
If Step is negative then the start number must be greater than the end number.
Exit the For Loop
Sometimes you may want to leave the loop earlier if a certain condition occurs. For example if you read bad data.
You can use Exit For to automatically leave the loop as shown in the following code
For i = 1 To 1000 ' If cell is blank then exit for If Cells(i, 1) = "" Then MsgBox "Blank Cell found - Data error" Exit For End If Next i
Using the VBA For Loop with a Collection
The For loop can also be used to read items in a Collection.
In the following example, we display the name of all the open workbooks
Dim i As Long For i = 1 To Workbooks.Count Debug.Print Workbooks(i).FullName Next i
Using Nested For Loops
Sometimes you may want to use a loop within a loop. An example of this would be where you want to print the names of the worksheets of each open workbook.
The first loop would go through each workbook. Each time this loop runs it would use a second loop to go through all the worksheets of that workbook. It is actually much easier to do than it sounds.
The following code shows how:
' https://excelmacromastery.com/ Sub ListWorksheets() Dim i As Long, j As Long ' First Loop goes through all workbooks For i = 1 To Workbooks.Count ' Second loop goes through all the worksheets of workbook(i) For j = 1 To Workbooks(i).Worksheets.Count Debug.Print Workbooks(i).Name + ":" + Worksheets(j).Name Next j Next i End Sub
This works as follows:
The first loop sets i to 1
The second loop then uses the workbook at 1 to go through the worksheets.
The first loop sets i to 2
The second loop then uses the workbook at 2 to go through the worksheets.
and so on
It the next section we will use a For Each loop to perform the same task. You will find the For Each version much easier to read.
The VBA For Each Loop
The VBA For Each loop is used to read items from a collection or an array. We can use the For Each loop to access all the open workbooks. This is because Application.Workbooks is a collection of open workbooks.
This is a simple example of using the For Each Loop
Dim wk As Workbook For Each wk In Workbooks Debug.Print wk.FullName Next wk
Format of the VBA For Each Loop
You can see the format of the VBA for each loop here(See Microsoft For Each Next documentation):
For Each <variable> in <collection>
Next <variable>
To create a For Each loop we need a variable of the same type that the collection holds. In the example here we created a variable of type Workbook.
If the collection has different types of items we can declare the variable as a variant.
VBA contains a collection called Sheets. This is a collection of sheets of type Worksheet(normal) and Chart(when you move a chart to be a full sheet). To go through this collection you would declare the variable as a Variant.
The following code uses For Each to print out the name of all the sheets in the current workbook
Dim sh As Variant For Each sh In ThisWorkbook.Sheets Debug.Print sh.Name Next sh
Order of Items in the For Loop
For Each goes through items in one way only.
For example, if you go through all the worksheets in a workbook it will always go through from left to right. If you go through a range it will start at the lowest cell e.g. Range(“A1:A10”) will return A1,A2,A3 etc.
This means if you want any other order then you need to use the For loop.
Both loops in the following example will read the worksheets from left to right:
' Both loops read the worksheets from left to right Dim wk As Worksheet For Each wk In ThisWorkbook.Worksheets Debug.Print wk.Name Next Dim i As Long For i = 1 To ThisWorkbook.Worksheets.Count Debug.Print ThisWorkbook.Worksheets(i).Name Next
As you can see the For Each loop is neater to write. However if you want to read the sheets in any other order e.g. right to left then you have to use the for loop:
' Reading the worksheets from right to left Dim i As Long For i = ThisWorkbook.Worksheets.Count To 1 Step -1 Debug.Print ThisWorkbook.Worksheets(i).Name Next
Using the VBA For Each Loop With Arrays
One thing to keep in my is that the For Each loop is that it is read-only when you use it with arrays.
The following example demonstrates this:
' https://excelmacromastery.com/ Sub UseForEach() ' Create array and add three values Dim arr() As Variant arr = Array("A", "B", "C") Dim s As Variant For Each s In arr ' Changes what s is referring to - not value of array item s = "Z" Next ' Print items to show the array has remained unchanged For Each s In arr Debug.Print s Next End Sub
In the first loop we try to assign s to “Z”. When happens is that s is now referring the string “Z” and no longer to the item in the array.
In the second loop we print out the array and you can see that none of the values have changed.
When we use the For Loop we can change the array item. If we change the previous code to use the For Loop you it will change all the array values to “Z”
' https://excelmacromastery.com/ Sub UsingForWithArray() ' Create array and add three values Dim arr() As Variant arr = Array("A", "B", "C") Dim i As Long For i = LBound(arr) To UBound(arr) ' Changes value at position to Z arr(i) = "Z" Next ' Print items to show the array values have change For i = LBound(arr) To UBound(arr) Debug.Print arr(i) Next End Sub
If your Collection is storing Objects the you can change the items using a For Each loop.
Using Nested For Each Loops
We saw already that you can have a loop inside other loops. Here is the example from above:
' https://excelmacromastery.com/ Sub ListWorksheets() Dim i As Long, j As Long ' First Loop goes through all workbooks For i = 1 To Workbooks.Count ' Second loop goes through all the worksheets of workbook(i) For j = 1 To Workbooks(i).Worksheets.Count Debug.Print Workbooks(i).Name + ":" + Worksheets(j).Name Next j Next i End Sub
This time we will use the For Each loop to perform the same task:
' https://excelmacromastery.com/ Sub ReadAllWorksheets() Dim wk As Workbook, sh As Worksheet ' Read each workbook For Each wk In Workbooks ' Read each worksheet in the wk workbook For Each sh In wk.Worksheets ' Print workbook name and worksheet name Debug.Print wk.Name + ": " + sh.Name Next sh Next wk End Sub
As you can see this is a neater way of performing this task than using the For Loop:
This code run as follows:
- Get the first Workbook from the Workbooks collection
- Go through all the worksheets in this workbook
- Print the workbook/worksheet details
- Get the next workbooks in the collection
- Repeat steps 2 to 3
- Continue until no more workbooks are left in the collection
How to Loop Through a Range
In Excel VBA, the most common use of a For Loop is to read through a range.
Imagine we have the data set in the screenshot below. Our task is to write code that will read through the data and copy the amounts to the column J. We are only going to copy amounts that are greater than 200,000.
The following example shows how we do it:
' Read through an Excel Range using the VBA For Loop ' https://excelmacromastery.com/ Sub ForLoopThroughRange() ' Get the worksheet Dim sh As Worksheet Set sh = ThisWorkbook.Worksheets("Sheet1") ' Get the Range Dim rg As Range Set rg = sh.Range("A1").CurrentRegion ' Delete existing output sh.Range("J1").CurrentRegion.ClearContents ' Set the first output row Dim row As Long row = 1 ' Read through all the rows using the For Loop Dim i As Long For i = 2 To rg.Rows.Count ' Check if amount is greater than 200000 If rg.Cells(i, 4).Value > 200000 Then ' Copy amount to column m sh.Cells(row, "J").Value = rg.Cells(i, 4).Value ' Move to next output row row = row + 1 End If Next i End Sub
This is a very basic example of copying data using Excel VBA. If you want a complete guide to copying data using Excel VBA then check out this post
Summary of the VBA For Loops
The Standard VBA For Loop
- The For loop is slower than the For Each loop.
- The For loop can go through a selection of items e.g. 5 to 10.
- The For loop can read items in reverse e.g. 10 to 1.
- The For loop is not as neat to write as the For Each Loop especially with nested loops.
- To exit a For loop use Exit For.
The VBA For Each Loop
- The For Each loop is faster than the For loop.
- The For Each loop goes through all items in the collectionarray.
- The For Each loop can go through items in one order only.
- The For Each loop is neater to write than a For Loop especially for nested loops.
- To exit a For Each loop use Exit For.
What’s Next?
Free VBA Tutorial If you are new to VBA or you want to sharpen your existing VBA skills then why not try out the The Ultimate VBA Tutorial.
Related Training: Get full access to the Excel VBA training webinars.
(NOTE: Planning to build or manage a VBA Application? Learn how to build 10 Excel VBA applications from scratch.)