VBA Range Object: How to Work with Cells

VBA & macros · Updated November 3, 2026

VBA Range Object: How to Work with Cells

The Excel VBA Range object represents one or more cells on a worksheet, letting code read or change values, formulas, and formatting. To refer to a cell reliably, qualify it with its worksheet, such as Worksheets("Data").Range("B2"), rather than relying on whichever sheet happens to be active.

What the Range Object Represents

In Excel’s object model, a Range is an object for a cell or a collection of cells. It can describe a single cell, a rectangular block, an entire row or column, or—in some operations—a set of separate areas. A worksheet’s Range property returns that object; properties and methods on it let a macro inspect or change the referenced cells.

For example, a range can point to one input cell, a column of names, or a block of data. The object is not the cell’s value itself. The value is one of its properties, commonly accessed through .Value or .Value2. Keeping that distinction in mind helps explain why VBA uses the Set keyword when assigning a range to an object variable, but not when assigning a cell’s text to a normal variable.

A range reference also has a worksheet context. The same address, such as B2, exists on every sheet, so a dependable macro specifies which sheet it means. This is especially important in workbooks with multiple tabs or code that runs while a user is viewing a different sheet.

How to Refer to Cells and Blocks

The most familiar reference uses an address in quotation marks. Use a worksheet object before .Range when the target must not depend on the active sheet. The following examples show typical address forms:

  • ws.Range("A1") refers to one cell.
  • ws.Range("A1:C10") refers to a rectangular block.
  • ws.Range("B:B") refers to an entire column.
  • ws.Range("2:2") refers to an entire row.

For code that uses numbers for row and column positions, use the worksheet’s Cells property. Its arguments are row number first and column number second, so ws.Cells(3, 2) means B3. Combining Range and Cells is useful when the row number is calculated while the macro runs. For instance, a block can start at row 2 and end at a variable last row.

Assigning a Range to an object variable uses Set. Here is a small, complete macro that writes to a specified cell:

Sub WriteStatus()
    Dim ws As Worksheet
    Dim target As Range

    ' Identify the sheet and cell explicitly.
    Set ws = ThisWorkbook.Worksheets("Data")
    Set target = ws.Range("B2")
    target.Value = "Ready"
End Sub

Before running a macro that changes a workbook, save a copy: VBA changes cannot be reversed with Ctrl+Z. On Windows, open the Visual Basic Editor with Alt+F11; on a Mac, use Developer > Visual Basic or the keyboard shortcut available for that Mac’s keyboard configuration.

Building References That Change with the Data

Fixed addresses work well for stable layouts, but many lists grow over time. A common pattern is to find the last used row in a known column, then build a range using Cells. The method below travels upward from the bottom of the worksheet to the first nonempty cell in column A:

Sub MarkPopulatedRows()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim dataRange As Range

    Set ws = ThisWorkbook.Worksheets("Data")
    ' Assumes column A has no gaps in the data list.
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    If lastRow >= 2 Then
        Set dataRange = ws.Range(ws.Cells(2, 1), ws.Cells(lastRow, 1))
        dataRange.Interior.Color = RGB(255, 255, 0)
    End If
End Sub

This example assumes row 1 is a header and that column A is the column used to identify the list’s extent. If column A contains gaps, the last nonempty cell can still be found, but the range will include those gaps. If the chosen column may be empty while other columns contain data, choose a more dependable column or determine the final row from the actual data structure.

Another option is CurrentRegion, which returns the contiguous block around a cell, stopping at blank rows or columns. It is convenient for a clean rectangular data set, but a blank row inside the list can split the region. UsedRange returns the worksheet’s used area, but formatting left far below or to the right of visible data can make that area larger than expected. Neither property is a universal substitute for defining what counts as the data.

Reading and Writing Values

Use .Value to get or set a cell’s value. For a single cell, reading it into a variable is straightforward. For a rectangular range, assigning a two-dimensional array to the range can transfer many values at once, which is often faster than looping through cells individually.

.Value2 is often preferred when transferring raw worksheet values because it does not return VBA Currency or Date subtypes; dates and currency-formatted numbers are generally returned as numeric values. The cell’s number format controls how Excel displays those numbers. Choose .Value when its Date or Currency conversion behavior is useful, and choose .Value2 when working with underlying values in bulk.

Writing to every cell in a multi-cell range with one scalar value puts that value in each cell. Reading a rectangular range into a Variant generally returns a two-dimensional array, so code should not assume it receives one simple value. A one-cell range behaves differently from a multi-cell range, which is worth accounting for when a variable-size selection might contain just one cell.

To change a formula rather than its calculated result, use the .Formula property. For example, code can place a formula into a cell and let Excel calculate it. Assigning to .Value instead writes a value; it does not preserve a formula as a formula. When a macro needs to keep existing formulas intact, it should target only the cells intended for input or output.

Changing Formatting and Other Range Properties

A Range object exposes more than cell contents. Its properties include font, interior fill, number format, borders, and alignment. These properties can apply to one cell or a whole block. For example, a macro can set .NumberFormat for a column of dates or set .Font.Bold for a header range.

Choose clearing methods according to what should remain. .ClearContents removes values and formulas but keeps formatting. .ClearFormats removes formatting while leaving contents. .Clear removes both contents and formatting, so it can have a wider impact than intended. Before clearing a large range, confirm its address and whether it includes headers, notes, or formulas that need to stay.

Ranges also support methods for tasks such as copying, inserting, deleting, and finding cells. Those operations can shift nearby data or affect formatting, so the method should be applied to a precisely identified range. For code that changes an entire row or column, use properties such as .EntireRow or .EntireColumn deliberately: they refer beyond the cells initially selected.

Worksheet Qualification and Selection

In a standard code module, an unqualified reference such as Range("A1") normally refers to the active worksheet. If the user switches sheets, the same macro can then read or modify a different cell than intended. Qualifying the reference—ThisWorkbook.Worksheets("Data").Range("A1")—makes the target explicit. ThisWorkbook means the workbook containing the VBA code; ActiveWorkbook means the workbook currently active in Excel, which may be a different file.

There is a related distinction between referring to a range and selecting it. Most code does not need to select or activate cells at all. It can write directly to a qualified range, which avoids changing the user’s view and reduces reliance on active-sheet state. Selection is appropriate when the macro’s purpose is to guide the user to a location, but it is usually unnecessary for routine data processing.

Worksheet code modules have their own context, so an unqualified Range there refers to that worksheet. Explicit qualification is still useful for readability and makes code easier to move or review. For multiple separate blocks, use Excel’s Union method to combine ranges on the same worksheet rather than assuming a rectangular block covers them.

Common Errors and Misconceptions

  • “Range means the value.” It means the cell or cells. Read or write the value through a property such as .Value.
  • “A1 always means the same cell.” Its address is the same, but an unqualified reference can depend on the active sheet. Qualify it when the target matters.
  • “Set is required for every assignment.” Use Set when assigning an object reference, such as a Range to a variable. Do not use it to assign a string or number to a cell’s value.
  • “The last used row is obvious.” It depends on which column or rule defines the data. A blank in the chosen column, an empty sheet, or leftover formatting can change results.

Another frequent issue is a misspelled worksheet name. A reference such as Worksheets("Data") raises an error if there is no worksheet with that tab name in the specified workbook. Check the sheet name and workbook context, and consider handling an absent sheet when the macro is intended to run across files with varying layouts.

Range dimensions matter too. Assigning a two-dimensional array to a range of incompatible dimensions can produce an error or an unexpected result. Confirm that the array’s row and column counts match the destination. Also avoid using Select merely to make a reference work; direct object references are more robust and usually easier to maintain.

Frequently Asked Questions

What is a Range object in VBA?
A Range object represents one or more Excel worksheet cells. VBA can use it to read and write data, inspect formulas, change formatting, or perform operations such as copying and clearing.

How do I refer to a cell in another worksheet?
Use the worksheet object before .Range, for example ThisWorkbook.Worksheets("Data").Range("C5"). This specifies the workbook and sheet instead of relying on the active worksheet.

What is the difference between Range and Cells?
Range commonly uses an address such as A1 or A1:C5. Cells uses numeric row and column indexes, which makes it useful when those positions are calculated in code. Both can return a range reference.

Why does VBA use Set with a Range variable?
A range variable stores a reference to an object, so VBA uses Set when assigning that reference. Assigning a value to a cell is different: set the cell’s .Value property without Set.

Can a Range object refer to multiple cells?
Yes. It can represent a rectangular block, a full row or column, or separate areas combined with methods such as Union. Operations on a multi-cell range may behave differently from operations on one cell, especially when reading values into a variable.

Related

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

More in VBA & macros

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

Spotted an error in this guide? Let us know.