readxl anchored() in R: Read a Cell Block by Corner
readxl anchored() builds a rectangular cell range from a single upper-left corner and a c(rows, columns) size, then hands that range to read_excel() so it imports an exact block of cells without you ever computing the far corner.
anchored("B5", dim = c(10, 6)) # 10 rows x 6 cols, corner at B5
anchored(c(5, 2), dim = c(10, 6)) # same block, R-style c(row, column) anchor
anchored("A1") # single cell A1 (dim defaults to c(1, 1))
anchored("A1", dim = c(20, 4)) # rows 1-20, columns 1-4
read_excel(path, range = anchored("B5", dim = c(10, 6))) # feed it to read_excel()Need explanation? Read on for examples and pitfalls.
What anchored() does
anchored() describes a block by its corner and its size. You give it one upper-left cell and a dim pair that says how many rows tall and how many columns wide the block is. It returns a small cell_limits object, which you pass to the range argument of read_excel(). readxl then reads only the cells inside that block and ignores everything around it.
The function ships with readxl, re-exported from the cellranger package, so loading readxl is enough. It is the right helper when you know where a table starts and how big it is, but you would rather not do the arithmetic to find its bottom-right corner.
cell_limits object, but they ask for different inputs. Reach for anchored() when a block's dimensions are natural to state ("11 rows, 6 columns") and reach for cell_limits() when both corners are already known.anchored() syntax and arguments
anchored() takes one required idea and a few optional controls. The signature is anchored(anchor, dim, input), and each argument shapes a different part of the block.
| Argument | Default | Description |
|---|---|---|
anchor |
"A1" |
Upper-left cell. An A1 string such as "B5", or a c(row, column) pair. |
dim |
c(1, 1) |
Block size as c(rows, columns). Both values must be positive. |
input |
"R" |
How a numeric anchor is read. "R" means c(row, column). Ignored for A1 strings. |
The anchor counts as the first cell of the range, so a dim of c(11, 6) reaches from the anchor down 11 rows and across 6 columns, both inclusive. Printing the result shows the two corners it resolved to.
The corner B5 becomes row 5, column 2, and the c(10, 6) size extends it to row 14, column 7.
Read a block by its corner: four examples
Every example reads deaths.xlsx, a sample file bundled with readxl. Each sheet has four metadata rows on top, a header on row 5, ten data rows, and footer notes below, a realistic layout for testing ranges.
Read a fixed block
Anchor on the header row and size the block to cover the table. The header sits on row 5 and the data ends on row 15, so the block is 11 rows tall and 6 columns wide.
The first row of the range becomes the column header, so 11 anchored rows yield 10 data rows.
Anchor with R-style coordinates
A numeric c(row, column) anchor works the same as an A1 string. This is handy when the corner comes from a calculation rather than a literal cell reference.
The anchor c(5, 1) is read as row 5, column 1 because input defaults to "R".
Read a smaller block
Shrink dim to pull just a slice of the table. A dim of c(4, 6) covers the header plus three data rows.
Reuse a stored anchored range
Store the range once and apply it to every file with the same layout. Because a cell_limits object is independent of any file, one definition serves many reads.
cell_limits(c(5, 1), c(15, 6), sheet = "other") or an A1 string such as "other!A5:F15", both of which carry the sheet inside the range.anchored() vs cell_limits() vs A1 ranges
Three ways to name a range trade off arithmetic against clarity. They all reach the same block of cells; they differ in what you have to know up front.
| Approach | You supply | Best for |
|---|---|---|
anchored() |
One corner plus a c(rows, columns) size |
A block whose dimensions are natural to state |
cell_limits() |
Two corners as c(row, column) pairs |
A rectangle when both corners are already known |
| A1 string | An Excel range like "B5:F15" |
Quick ranges you can read straight off the sheet |
Use anchored() when the block's height and width are obvious but the bottom-right corner would need a calculation. Use cell_limits() when both corners are known. Reach for an A1 string when you want the shortest possible code and the range fits Excel notation cleanly.
anchored() equivalent. You combine arguments instead: pd.read_excel(path, header=4, usecols="A:F", nrows=10) reproduces anchored("A5", dim = c(11, 6)) by pairing a header offset, a column span, and a row count.Common pitfalls
Most anchored() mistakes come from misreading dim. Three problems account for nearly every wrong block.
dimis a size, not a corner. It is ac(rows, columns)height-and-width pair, never the lower-right cell. Passing a far corner asdimreaches well past the data.dimisc(rows, columns), notc(columns, rows). Swapping the order silently reads a block of the wrong shape.- The anchor counts as the first row. A block anchored on the header row needs one extra row in
dimto cover every data row.
Try it yourself
Try it: Read a 5-row by 6-column block starting at cell A5 of the deaths.xlsx example file. Save the result to ex_block.
Click to reveal solution
Explanation: A dim of c(5, 6) spans 5 rows from the anchor. Row 5 is the header, which leaves 4 data rows and all 6 columns.
Related readxl functions
These functions pair naturally with anchored() when importing spreadsheet data:
- read_excel() reads xls and xlsx files;
anchored()feeds itsrangeargument. - cell_limits() defines a range from two corner coordinates instead of a corner and a size.
- cell_rows() limits a read by row numbers only, keeping every column.
- cell_cols() limits a read by column numbers or letters only, keeping every row.
- excel_sheets() lists sheet names so you can choose a sheet before setting a range.
See the official readxl cell-specification reference for the full family of range helpers.
FAQ
What does anchored() do in readxl?
anchored() creates a cell_limits object that describes a rectangular block of cells. You give it one upper-left corner and a dim pair stating how many rows and columns the block covers. The object stores nothing from the file; it is a specification. You pass it to the range argument of read_excel(), and readxl reads only the cells inside that block, skipping the rows and columns around it.
What is the difference between anchored() and cell_limits()?
Both build a cell_limits object, but they take different inputs. anchored() wants one corner plus a c(rows, columns) size, so you describe the block by where it starts and how big it is. cell_limits() wants two corners, an upper-left and a lower-right c(row, column) pair. Use anchored() when the dimensions are easy to state, and cell_limits() when both corners are already known.
How is the dim argument ordered in anchored()?
dim is a c(rows, columns) pair: rows first, columns second. It is a size, a height and a width, not the lower-right corner of the block. A dim of c(11, 6) reaches 11 rows down and 6 columns across from the anchor, with the anchor counting as the first cell. Reversing the order to c(6, 11) reads a block of the wrong shape without raising an error.
Can anchored() read from a specific worksheet?
No. anchored() has no sheet argument, so the block it builds always targets the first sheet. To read a block from a named sheet, attach the sheet to the range some other way. Use cell_limits(c(5, 1), c(15, 6), sheet = "other"), which accepts a sheet argument, or pass an A1 string like "other!A5:F15" to the range argument of read_excel().