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