Normal named-range tables — visual walkthrough

A managed table is a hand-authored header row whose live data extent is tracked by two sheet-scoped bookmarks. This page walks the whole lifecycle — register, first paste, grow / shrink, widen, read back — using the real functions from the manual-tables guide. No Benchling required.

Header row (anchor) Selected before init Live data cell Auto-added column (widen) Inserted / shifted rows Cleared cell (shrink / narrow)

Throughout: the anchor named range sample_table points at the header row; the bookmark pair sample_table_table_start / sample_table_table_end tracks the top-left and bottom-right data cells. You never write the bookmarks by hand — the package maintains them.

1. Select the header row, then register named ranges SETUP

Type your column headers across one contiguous row in Excel. Select that header range and call initialise_table_named_ranges(wb, "sample_table", scope_sheet="Inputs"). The scan names every header cell and leaves the header text untouched.

Before — header typed & selected
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
3
After — names registered (cells unchanged)
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
3

Select A1:D1, then call initialise_table_named_ranges. It creates: the anchor sample_table on the header row (if you made it in the Name Box) plus one per-column named range per header cell — Sample_No. = $A$1, Sample_ID = $B$1, Conc_mg = $C$1, Result = $D$1. Spaces and punctuation collapse to _; case is preserved. With the header alone and no data yet, no bookmarks are written — the first paste creates them.

2. First paste fills the data rows paste_df_to_named_range

paste_df_to_named_range(wb, df, "sample_table", scope_sheet="Inputs") writes df.values into the rows directly below the header (the index is never written). Columns are matched positionally against the header cells.

Before — header only, no bookmarks
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
3
4
After — 3-row DataFrame written
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
start1
VS0001
12.4
Pass
3
2
VS0002
9.8
Pass
4
3
VS0003
15.1
endFail

The first paste writes the bookmark pair: sample_table_table_start at the top-left data cell (A2) and sample_table_table_end at the bottom-right (D4). If a DataFrame column label doesn't line up with the header at its position, the call raises ColumnOrderMismatchError before touching the sheet.

3. Grow and shrink on re-paste row delta

Re-pasting a larger DataFrame inserts rows below the old extent (anything stacked below shifts down). A smaller DataFrame clears the trailing rows and collapses the band. Either way the _table_end bookmark follows the new last data row.

Grow — 3 rows → 5 rows

Before — data rows 2–4
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
start1
VS0001
12.4
Pass
3
2
VS0002
9.8
Pass
4
3
VS0003
15.1
endFail
After — +2 rows inserted, end moves to row 6
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
start1
VS0001
12.4
Pass
3
2
VS0002
9.8
Pass
4
3
VS0003
15.1
Fail
↓ 2 rows inserted below old extent
5
4
VS0004
8.2
Pass
6
5
VS0005
11.0
endPass

Shrink — 3 rows → 1 row

Before — data rows 2–4
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
start1
VS0001
12.4
Pass
3
2
VS0002
9.8
Pass
4
3
VS0003
15.1
endFail
After — trailing rows cleared, end at row 2
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
start/end1
VS0001
12.4
Pass
↑ band collapses; rows below pulled up
3
4

Under the stacked-only invariant, shrink is unconditionally safe — no other managed table shares these rows, so nothing side-by-side can be destroyed. A stacked neighbour below moves up by exactly the row-count delta.

4. Widen — DataFrame brings an extra column auto-extend header

When df has more columns than the current header, paste_df_to_named_range auto-extends the header and the new header cell takes its label from df.columns. Safe because the stacked-only invariant guarantees nothing shares the table's rows.

Before — header width 4 (A–D)
A
B
C
D
E
1
Sample No.
Sample ID
Conc (mg)
Result
2
start1
VS0001
12.4
Pass
3
2
VS0002
9.8
endPass
After — header extended to E, new column filled
A
B
C
D
E
1
Sample No.
Sample ID
Conc (mg)
Result
Operator
2
start1
VS0001
12.4
Pass
A.K.
3
2
VS0002
9.8
Pass
endR.S.

A new per-column named range is created for the added header (Operator = $E$1) and the _table_end bookmark now reaches column E. Overflowing past Excel's last column (XFD = 16,384) raises ExcelColumnOverflowError. Conversely, a narrower DataFrame clears the trailing data cells but keeps the declared header width.

5. Read the table back into a DataFrame import_excel_table · scan_named_range_table

Two readers return a (DataFrame, mapping) tuple; they differ in how they find the table boundaries. Both read the highlighted region below — the header plus the live data extent between the bookmarks.

import_excel_table — from the header anchor
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
start1
VS0001
12.4
Pass
3
2
VS0002
9.8
endPass

Pass the anchor name; data rows are discovered by scanning down from the header. Width comes from the anchor's column extent. Bookmarks are auto-healed and grown (never auto-shrunk) on every call. Default columns are range-name tokens (use_name_range_names=True); an all-null column raises EmptyDataError when check_empty_columns=True.

scan_named_range_table — from start/end bookmarks
A
B
C
D
1
Sample No.
Sample ID
Conc (mg)
Result
2
start1
VS0001
12.4
Pass
3
2
VS0002
9.8
endPass

Use when there's no anchor — only the bookmarks. Pass table_start_name + table_end_name; the header row is inferred as the row immediately above table_start, and the right edge is found by scanning header cells rightward to the first blank one (keep the header contiguous). Default columns are the display headers.

get_named_range_results, get_value, and get_list_results read individual cells or a single column slice between two row markers — handy when you don't need the whole frame.

Formula-injection guard (default sanitize_formulas=True). On paste, text cells beginning with =, +, -, or @ are apostrophe-escaped so externally-sourced data can't smuggle a live Excel formula into the sheet. Numbers and numeric-looking strings ("-5.3", "+1e3") are left alone, so bio labels like "+/+" and "-/-" survive as text. Pass sanitize_formulas=False only for a trusted source where you want real formulas written through verbatim. Regardless of the flag: ±inf becomes an empty cell, and strings over Excel's 32,767-char per-cell limit are truncated (with one UserWarning).