Let’s say I have the following code:
Sub TestRangeLoop()
Dim rng As Range
Set rng = Range("A1:A6")
''//Insert code to loop through rng here
End Sub
I want to be able to iterate through a collection of Range
objects for each cell specified in rng
. Conceptually, I’d like to do it like so:
For Each rngCell As Range in rng
''//Do something with rngCell
Next
I know I could solve this by parsing rng.Address
and building Range
objects manually, but I’m hoping there is a more direct way that doesn’t involve string parsing.
Teamothy
1,9903 gold badges15 silver badges24 bronze badges
asked Oct 6, 2010 at 17:48
Ben McCormackBen McCormack
31.8k46 gold badges145 silver badges221 bronze badges
Sub LoopRange()
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheet1.Range("A1:A6")
For Each rCell In rRng.Cells
Debug.Print rCell.Address, rCell.Value
Next rCell
End Sub
answered Oct 6, 2010 at 18:13
Dick KusleikaDick Kusleika
32.5k4 gold badges51 silver badges73 bronze badges
5
You could use Range.Rows
, Range.Columns
or Range.Cells
. Each of these collections contain Range
objects.
Here’s how you could modify Dick’s example so as to work with Rows
:
Sub LoopRange()
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheet1.Range("A1:A6")
For Each rCell In rRng.Rows
Debug.Print rCell.Address, rCell.Value
Next rCell
End Sub
And Columns
:
Sub LoopRange()
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheet1.Range("A1:A6")
For Each rCol In rRng.Columns
For Each rCell In rCol.Rows
Debug.Print rCell.Address, rCell.Value
Next rCell
Next rCol
End Sub
answered Oct 6, 2010 at 18:10
4
To make a note on Dick’s answer, this is correct, but I would not recommend using a For Each loop. For Each creates a temporary reference to the COM Cell behind the scenes that you do not have access to (that you would need in order to dispose of it).
See the following for more discussion:
How do I properly clean up Excel interop objects?
To illustrate the issue, try the For Each example, close your application, and look at Task Manager. You should see that an instance of Excel is still running (because all objects were not disposed of properly).
A cleaner way to handle this is to query the spreadsheet using ADO:
http://technet.microsoft.com/en-us/library/ee692882.aspx
answered Oct 6, 2010 at 18:21
Mark AveniusMark Avenius
13.6k6 gold badges41 silver badges50 bronze badges
5
I’m resurrecting the dead here, but because a range can be defined as «A:A», using a for each loop ends up with a potential infinite loop. The solution, as far as I know, is to use the Do Until
loop.
Do Until Selection.Value = ""
Rem Do things here...
Loop
answered Dec 9, 2015 at 0:37
NielsvhNielsvh
1,1321 gold badge19 silver badges31 bronze badges
1
In this Article
- For Each Loop
- For Each: Basic Examples
- Loop Through Cells
- Loop Through Sheets
- Loop Through Workbooks
- Loop Through Shapes
- Loop Through Charts
- Loop Through PivotTables
- Loop Through Tables
- Loop Through Items in Array
- Loop Through Numbers
- For Each Loop Builder
- For Each – If
- For Each Cell in Range – If
- For Each Common Examples
- Close All Workbooks
- Hide All Sheets
- Unhide All Sheets
- Protect All Sheets
- Unprotect All Sheets
- Delete All Shapes On All Worksheets
- Refresh All PivotTables
- Using For Each in Access VBA
This tutorial will show you examples of using the For Each Loop in VBA. Click here to learn more about loops in general.
For Each Loop
The For Each Loop allows you to loop through each object in a collection:
- All cells in a range
- All worksheets in a workbook
- All open workbooks
- All shapes in a worksheet
- All items in an array
- and more!
For Each: Basic Examples
These examples will demonstrate how to set up For Each loops to loop through different types of objects.
Loop Through Cells
This procedure will loop through each cell in range A1:A10, setting the cell to it’s right equal to itself.
Sub ForEachCell()
Dim Cell As Range
For Each Cell In Sheets("Sheet1").Range("A1:A10")
Cell.Offset(0, 1).value = Cell.value
Next Cell
End Sub
Loop Through Sheets
This procedure will loop through each sheet in a Workbook, unhiding each sheet.
Sub ForEachSheets()
Dim ws As Worksheet
For Each ws In Sheets
ws.Visible = True
Next ws
End Sub
Loop Through Workbooks
This procedure will loop through each Workbook, closing each one.
Sub ForEachWorkbooks()
Dim wb As Workbook
For Each wb In Workbooks
wb.Close
Next wb
End Sub
Loop Through Shapes
This procedure will loop through each shape in Sheet1, deleting each one.
Sub ForEachShape()
Dim Shp As Shape
For Each Shp In Sheets("Sheet1").Shapes
Shp.Delete
Next Shp
End Sub
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
Loop Through Charts
This procedure will loop through each Chart in Sheet1, deleting each one.
Sub ForEachCharts()
Dim cht As ChartObject
For Each cht In Sheets("Sheet1").ChartObjects
cht.Delete
Next cht
End Sub
Loop Through PivotTables
This procedure will loop through each PivotTable in Sheet1, clearing each one
Sub ForEachPivotTables()
Dim pvt As PivotTable
For Each pvt In Sheets("Sheet1").PivotTables
pvt.ClearTable
Next pvt
End Sub
Loop Through Tables
This procedure will loop through each Table in Sheet1, deleting each one.
Sub ForEachTables()
Dim tbl As ListObject
For Each tbl In Sheets("Sheet1").ListObjects
tbl.Delete
Next tbl
End Sub
VBA Programming | Code Generator does work for you!
Loop Through Items in Array
This procedure will loop through each item in an Array, display each value in a msgbox,
Sub ForEachItemInArray()
Dim arrValue As Variant
Dim Item As Variant
arrValue = Array("Item 1", "Item 2", "Item 3")
For Each Item In arrValue
MsgBox Item
Next Item
End Sub
Loop Through Numbers
This procedure will loop through each number in an Array, display each value in a msgbox,
Sub ForEachNumberInNumbers()
Dim arrNumber(1 To 3) As Integer
Dim num As Variant
arrNumber(1) = 10
arrNumber(2) = 20
arrNumber(3) = 30
For Each num In arrNumber
Msgbox num
Next num
End Sub
For Each Loop Builder
The examples in this article were built with the Loop Builder in our VBA Add-in: AutoMacro.
The Loop Builder makes it very easy to generate code to loop through objects. AutoMacro also contains many other Code Generators, an extensive Code Library, and powerful Coding Tools.
For Each – If
You can also use If Statements within Loops to test if objects meet certain criteria, only performing actions on those objects that meet the criteria. Here is an example of looping through each cell in a range:
For Each Cell in Range – If
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
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
For Each Common Examples
Close All Workbooks
This procedure will close all open workbooks, saving changes.
Sub CloseAllWorkbooks()
Dim wb As Workbook
For Each wb In Workbooks
wb.Close SaveChanges:=True
Next wb
End Sub
Hide All Sheets
This procedure will hide all worksheets.
Sub HideAllSheets()
Dim ws As Worksheet
For Each ws In Sheets
ws.Visible = xlSheetHidden
Next ws
End Sub
Unhide All Sheets
This procedure will unhide all worksheets.
Sub UnhideAllSheets()
Dim ws As Worksheet
For Each ws In Sheets
ws.Visible = xlSheetVisible
Next ws
End Sub
AutoMacro | Ultimate VBA Add-in | Click for Free Trial!
Protect All Sheets
This procedure will protect all worksheets.
Sub ProtectAllSheets()
Dim ws As Worksheet
For Each ws In Sheets
ws.Protect Password:="..."
Next ws
End Sub
Unprotect All Sheets
This procedure will unprotect all worksheets.
Sub UnprotectAllSheets()
Dim ws As Worksheet
For Each ws In Sheets
ws.Unprotect Password:="..."
Next ws
End Sub
Delete All Shapes On All Worksheets
This procedure will delete all shapes in a workbook.
Sub DeleteAllShapesOnAllWorksheets()
Dim Sheet As Worksheet
Dim Shp As Shape
For Each Sheet In Sheets
For Each Shp In Sheet.Shapes
Shp.Delete
Next Shp
Next Sheet
End Sub
Refresh All PivotTables
This procedure will refresh all PivotTables on a sheet.
Sub RefreshAllPivotTables()
Dim pvt As PivotTable
For Each pvt In Sheets("Sheet1").PivotTables
pvt.RefreshTable
Next pvt
End Sub
Using For Each in Access VBA
The For Each loop works the same way in Access VBA as it does in Excel VBA. The following example will remove all the tables in the current database.
Sub RemoveAllTables()
Dim tdf As TableDef
Dim dbs As Database
Set dbs = CurrentDb
For Each tdf In dbs.TableDefs
DoCmd.DeleteObject tdf.Name
Loop
Set dbs = Nothing
End Sub
Цикл 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 following is a summary of the steps we need to accomplish to perform this task:
- Write a macro that will loop through each cell in the used range of a sheet. We don’t want to loop through all 17 billion cells of the sheet; only the used cells.
- Set up a counter to keep track of the number of cells containing formulas. As we examine each cell in the used range, if the cell contains a formula we will add one to our counter.
- Once the examination is complete, display the result stored in the counter in cell B6 of the current worksheet.
- Create a macro button and assign the macro to the button. When the user clicks the button, the macro will execute and the value in cell B6 will be updated.
Writing the Macro
Open the Visual Basic Editor (Alt-F11 or Developer (tab) -> Code (group) -> Visual Basic).
Create a new module sheet called “ProjectActivity” by right-clicking on any item in the current workbook list of the Project Explorer and selecting Insert -> Module.
In the Properties windows, change the name of the new module sheet from Module1 to ProjectActivity.
In the code window we will create a new subprocedure named Count_If_Formula.
To loop through each cell, we will utilize a collection in conjunction with an IF…Then construct. The collection is the used range, and we need to declare a variable to hold a tiny part of the collection during the examination process. In this case, each tiny part is a single cell.
We need to establish a variable to hold the single cell during examination.
Now we will create the loop instruction to loop through each cell in the used range. Because “UsedRange” is a property of a worksheet, we can refer to the active sheet’s used range. We will go ahead and close the logic of the loop with the “Next cell” instruction.
Testing for the Presence of a Formula
Inside of the For…Next structure, let’s create a test to determine if the currently examined cell contains a formula. We will use an IF statement to compare the cell’s contents to the range property HasFormula.
The HasFormula property returns a “True” if the cell contains a formula.
Don’t forget to close the logic of the If…Then with an End If statement.
If the test of the cell returns a “True”, we need to keep record of that occurrence. We need to create a variable to store that occurrence. Then next time we encounter a formula, we will increment that counter by 1.
Create a new variable called “CountFormula” as a Long data type to store this value. The Long data type can hold a value in excess of 9 quadrillion, well in excess of the maximum 17 billion cells on a single sheet.
Accounting for the Presence of a Formula
If the examined cell possesses a formula, we will add 1 to the counter named “CountFormula”. This is performed by the following line of code.
When the macro begins, the value of the variable “CountFormula” is automatically set to 0 (zero). As we loop though each cell in the used range testing for the presence of a formula, if the cell contains a formula, we add 1 (one) to the variable. This overwrites the current value with the updated value.
Displaying the Final Value to the User
We want to show the user the result of the cell examinations. We want to display the value stored in the “CountFormula” variable in cell B3 of the current sheet. The following line of code will perform this action.
Adding a Macro Launch Button
Returning to the Excel workbook, we will add a macro launch button and assign the newly created macro to the button.
From the ribbon, select Developer (tab) -> Controls (group) -> Insert -> Form Controls -> Button (upper left option).
Click anywhere on the active sheet.
From the Assign Macro dialog box, select the Count_If_Formula macro from the list of available macros and select OK.
This will create the macro launch button on the sheet.
Rename the button to “Count Formula” by right-clicking on the button and selecting Edit Text.
You may need to resize the button to display the fully renamed text.
Testing the Macro
Click the Count Formula button and observe the value in cell B6. The current value is 2, since we have formulas in cells B8 and B9.
Add a formula to cell B10 (any formula will do) and execute the macro. The value of cell B6 has been updated to 3.
NOTE: In this case, since we are putting the button on the same sheet we are examining we don’t need to reference the sheet name. We can use “ActiveSheet” and directly use range and not have to specify the sheet. The assumption is that the sheet being examined is the active sheet. If you were going to put your button on a different sheet and you wanted it to count the formulas on this specific sheet, you need to reference the worksheet names.
The Completed Code
Sub Count_IF_Formula()
Dim cell As Range
Dim CountFormula As Long
For Each cell In ActiveSheet.UsedRange
If cell.HasFormula Then
CountFormula = CountFormula + 1
End If
Next cell
Range("B6").Value = CountFormula
End Sub
Published on: January 5, 2019
Last modified: February 17, 2023
Leila Gharani
I’m a 5x Microsoft MVP with over 15 years of experience implementing and professionals on Management Information Systems of different sizes and nature.
My background is Masters in Economics, Economist, Consultant, Oracle HFM Accounting Systems Expert, SAP BW Project Manager. My passion is teaching, experimenting and sharing. I am also addicted to learning and enjoy taking online courses on a variety of topics.
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.