Vba excel range for each cell in range

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's user avatar

Teamothy

1,9903 gold badges15 silver badges24 bronze badges

asked Oct 6, 2010 at 17:48

Ben McCormack's user avatar

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 Kusleika's user avatar

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

code4life's user avatar

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

Community's user avatar

answered Oct 6, 2010 at 18:21

Mark Avenius's user avatar

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

Nielsvh's user avatar

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!

automacro

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.

vba loop builder

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

vba for each cell in range

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:

  1. 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.
  2. 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.
  3. Once the examination is complete, display the result stored in the counter in cell B6 of the current worksheet.
  4. 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 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

Microsoft Most Valuable Professional

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.

A group of cells make up 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:

Results of counter loop through in Excel

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”.

Identical results for second macro

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:

Arrows showing the order that cells are processed

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).

Excel table showing client number, address, and postal code

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.

Excel table showing orders items and unit costs

'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.

Macro results

(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.

Three columns in a row in Excel are highlighted to delete

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.

Results of deletion

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:

Results look the same

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.

More sample order data in Excel

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

Results of the macro with rows highlighted

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.

Понравилась статья? Поделить с друзьями:
  • Vba excel switch case
  • Vba excel save as dialogue
  • Vba excel range for column
  • Vba excel subscript out of range что это
  • Vba excel rows переменная