iOfficeAI/OfficeCLI · error · ArgumentException
Import exceeds Excel's column limit: data would reach column
Error message
Import exceeds Excel's column limit: data would reach column {endColIdx} (maximum {ExcelMaxCol} / XFD). Reduce the CSV width or change the start cell. What it means
Thrown by ExcelHandler.Import as a DOS-hardening guard BEFORE writing any cells, when startColIdx + maxCols - 1 would exceed Excel's maximum of 16,384 columns (XFD). The check uses the widest row in the parsed CSV.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Import.cs:59
return "No data to import";
int maxCols = 0;
for (int r = 0; r < rows.Count; r++)
if (rows[r].Count > maxCols) maxCols = rows[r].Count;
// DOS-hardening: reject imports that exceed Excel's sheet dimensions
// BEFORE writing anything. Without this an over-sized CSV (e.g. >XFD
// columns or >1048576 rows) spun indefinitely instead of erroring.
const int ExcelMaxRow = 1048576;
const int ExcelMaxCol = 16384; // XFD (ColumnNameToIndex is 1-based)
long endRowReq = (long)startRow + rows.Count - 1;
if (endRowReq > ExcelMaxRow)
throw new ArgumentException(
$"Import exceeds Excel's row limit: data would reach row {endRowReq} " +
$"(maximum {ExcelMaxRow}). Reduce the CSV or change the start cell.");
long endColIdx = (long)startColIdx + maxCols - 1;
if (endColIdx > ExcelMaxCol)
throw new ArgumentException(
$"Import exceeds Excel's column limit: data would reach column {endColIdx} " +
$"(maximum {ExcelMaxCol} / XFD). Reduce the CSV width or change the start cell.");
// BUG-R11-import-dup-row BUG-11: import previously always appended a
// brand-new <row r="N">, producing duplicate row entries when the
// target rows already existed (Excel auto-repaired by keeping the
// first one, silently losing imported data). Upsert by RowIndex —
// reuse an existing row, otherwise insert a new one in sorted position.
//
// PERF(dos-hardening): the previous implementation re-scanned the whole
// SheetData (LINQ FirstOrDefault) for every imported row AND every cell,
// making a bulk import O(rows*cells * existing) — a 100k-row CSV took
// 9+ minutes. Pre-index existing rows once and walk them with an
// ascending cursor for sorted insertion; build a per-row cell index
// only when reusing a pre-existing row. Bulk-append into a fresh sheet
// is now linear.
var existingRows = sheetData.Elements<Row>()
.Where(rr => rr.RowIndex?.Value != null)View on GitHub (pinned to 1ced45e900)
Solutions
- Reduce the CSV width to at most (16384 - startColIdx + 1) columns.
- Start at A1 to use the full column budget.
- Drop unused columns or split wide data across multiple sheets/tables.
Example fix
// before
var csv = WideExport(); // 17,000 columns
excel.Import("/Sheet1", csv, ',', false, "A1");
// after
var maxCols = 16384 - ColumnNameToIndex("A");
var csv = TrimToWidth(WideExport(), maxCols);
excel.Import("/Sheet1", csv, ',', false, "A1"); Defensive patterns
Strategy: validation
Validate before calling
const int ExcelMaxCol = 16384;
var (startCol, startRow) = ExcelHandler.ParseCellReference(startCell.ToUpperInvariant());
long endCol = (long)ExcelHandler.ColumnNameToIndex(startCol) + maxCols - 1;
if (endCol > ExcelMaxCol)
throw new ArgumentException($"Import would reach column {endCol} (max {ExcelMaxCol}/XFD)."); Prevention
- Measure the widest CSV row before importing and reject or trim oversized payloads.
- Start at A1 to use the full column budget.
- Drop unused columns from wide exports.
When it happens
Trigger: Importing a CSV wider than Excel's column limit from the given startCell, e.g. startCell=A1 with a 17,000-column CSV, or startCell=Z1 (column 26) with a 16,400-column CSV.
Common situations: Wide exports from data tools (pandas to_csv with hundreds of columns is fine, but a transposed or mis-shaped export can exceed 16k); starting at a non-A column and underestimating the offset.
Related errors
- Import exceeds Excel's row limit: data would reach row {endR
- unsupported_type
- Property 'sqref' (or 'range'/'ref') is required for validati
- Invalid 'height' value: '{value}'. Row height must be betwee
- Invalid 'width' value: '{value}'. Column width must be betwe
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/e64a1278d90c0f8a.
Report an issue: GitHub.