pola-rs/polars · error · RuntimeError
sparkline data range/cols must all be adjacent
Error message
sparkline data range/cols must all be adjacent
What it means
RuntimeError raised by _inject_sparklines during write_excel: a sparkline's data columns must be adjacent in the worksheet, because an Excel sparkline charts one contiguous cell range. _adjacent_cols verifies the referenced columns form a consecutive block in the frame; if other columns sit between them, the range cannot be built.
Source
Thrown at py-polars/src/polars/io/spreadsheet/_write_utils.py:305
ws: Worksheet,
df: DataFrame,
table_start: tuple[int, int],
col: str,
*,
include_header: bool,
params: Sequence[str] | dict[str, Any],
) -> None:
"""Inject sparklines into (previously-created) empty table columns."""
from xlsxwriter.utility import xl_rowcol_to_cell
m: dict[str, Any] = {}
data_cols = params.get("columns") if isinstance(params, dict) else params
if not data_cols:
msg = "supplying 'columns' param value is mandatory for sparklines"
raise ValueError(msg)
elif not _adjacent_cols(df, data_cols, min_max=m):
msg = "sparkline data range/cols must all be adjacent"
raise RuntimeError(msg)
spk_row, spk_col, _, _ = _xl_column_range(
df, table_start, col, include_header=include_header, as_range=False
)
data_start_col = table_start[1] + m["min"]["idx"]
data_end_col = table_start[1] + m["max"]["idx"]
if not isinstance(params, dict):
options = {}
else:
# strip polars-specific params before passing to xlsxwriter
options = {
name: val
for name, val in params.items()
if name not in ("columns", "insert_after", "insert_before")
}
if "negative_points" not in options:
options["negative_points"] = options.get("type") in ("column", "win_loss")View on GitHub (pinned to df599052da)
Solutions
- Reorder the frame so the sparkline's data columns are consecutive: df.select(['a', 'c', 'b', ...]) or sparklines over ['a','b','c'] instead.
- Or narrow the sparkline to a contiguous subset of the columns you care about.
- Or split into multiple sparklines, one per contiguous block.
Example fix
# before
pl.write_excel(df, sparklines={'trend': ['a', 'c']}) # df order: a, b, c
# after
pl.write_excel(df.select('a', 'c', 'b'), sparklines={'trend': ['a', 'c']}) Defensive patterns
Strategy: validation
Validate before calling
def adjacent(df, cols):
idx = [df.columns.index(c) for c in cols]
return max(idx) - min(idx) == len(idx) - 1
for name, spec in sparklines.items():
cols = spec.get('columns') if isinstance(spec, dict) else spec
if not adjacent(df, cols):
df = df.select(*[c for c in df.columns if c not in cols], *cols) # group them
pl.write_excel(df, sparklines=sparklines) Try / catch
try:
pl.write_excel(df, sparklines=sparklines)
except RuntimeError as e:
if 'adjacent' in str(e):
cols = next(iter(sparklines.values()))
cols = cols.get('columns') if isinstance(cols, dict) else cols
ordered = [c for c in df.columns if c not in cols] + list(cols)
pl.write_excel(df.select(ordered), sparklines=sparklines)
else:
raise Prevention
- Design exports so each sparkline's data columns are written consecutively.
- Pin column order explicitly with df.select(...) instead of relying on pipeline order.
- Check adjacency (index span equals count) before calling write_excel.
When it happens
Trigger: pl.write_excel(df, sparklines={'trend': ['a', 'c']}) when df columns are ordered a, b, c — 'b' sits inside the range. Also triggered by dict form with a non-contiguous 'columns' list.
Common situations: Pointing a sparkline at summary columns scattered across a wide export (e.g. monthly totals with metric-label columns interleaved); frames reordered by a group_by/with_columns pipeline so previously adjacent columns no longer are.
Related errors
- cannot create a second {col!r} column
- supplying 'columns' param value is mandatory for sparklines
- invalid dtype_format value: {fmt!r} (expected format string,
- invalid table style key: {key!r}
- the given workbook object {wb.filename!r} is not the parent
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/c644b1653fdaf75c.
Report an issue: GitHub.