{"record":{"id":"e64a1278d90c0f8a","repo":"iOfficeAI/OfficeCLI","slug":"import-exceeds-excel-s-column-limit-data-would-re","errorCode":null,"errorMessage":"Import exceeds Excel's column limit: data would reach column {endColIdx} (maximum {ExcelMaxCol} / XFD). Reduce the CSV width or change the start cell.","messagePattern":"Import exceeds Excel's column limit: data would reach column (.+?) \\(maximum (.+?) / XFD\\)\\. Reduce the CSV width or change the start cell\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Import.cs","lineNumber":59,"sourceCode":"            return \"No data to import\";\n\n        int maxCols = 0;\n        for (int r = 0; r < rows.Count; r++)\n            if (rows[r].Count > maxCols) maxCols = rows[r].Count;\n\n        // DOS-hardening: reject imports that exceed Excel's sheet dimensions\n        // BEFORE writing anything. Without this an over-sized CSV (e.g. >XFD\n        // columns or >1048576 rows) spun indefinitely instead of erroring.\n        const int ExcelMaxRow = 1048576;\n        const int ExcelMaxCol = 16384; // XFD (ColumnNameToIndex is 1-based)\n        long endRowReq = (long)startRow + rows.Count - 1;\n        if (endRowReq > ExcelMaxRow)\n            throw new ArgumentException(\n                $\"Import exceeds Excel's row limit: data would reach row {endRowReq} \" +\n                $\"(maximum {ExcelMaxRow}). Reduce the CSV or change the start cell.\");\n        long endColIdx = (long)startColIdx + maxCols - 1;\n        if (endColIdx > ExcelMaxCol)\n            throw new ArgumentException(\n                $\"Import exceeds Excel's column limit: data would reach column {endColIdx} \" +\n                $\"(maximum {ExcelMaxCol} / XFD). Reduce the CSV width or change the start cell.\");\n\n        // BUG-R11-import-dup-row BUG-11: import previously always appended a\n        // brand-new <row r=\"N\">, producing duplicate row entries when the\n        // target rows already existed (Excel auto-repaired by keeping the\n        // first one, silently losing imported data). Upsert by RowIndex —\n        // reuse an existing row, otherwise insert a new one in sorted position.\n        //\n        // PERF(dos-hardening): the previous implementation re-scanned the whole\n        // SheetData (LINQ FirstOrDefault) for every imported row AND every cell,\n        // making a bulk import O(rows*cells * existing) — a 100k-row CSV took\n        // 9+ minutes. Pre-index existing rows once and walk them with an\n        // ascending cursor for sorted insertion; build a per-row cell index\n        // only when reusing a pre-existing row. Bulk-append into a fresh sheet\n        // is now linear.\n        var existingRows = sheetData.Elements<Row>()\n            .Where(rr => rr.RowIndex?.Value != null)","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Import.cs#L41-L77","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar csv = WideExport();          // 17,000 columns\nexcel.Import(\"/Sheet1\", csv, ',', false, \"A1\");\n\n// after\nvar maxCols = 16384 - ColumnNameToIndex(\"A\");\nvar csv = TrimToWidth(WideExport(), maxCols);\nexcel.Import(\"/Sheet1\", csv, ',', false, \"A1\");","handlingStrategy":"validation","validationCode":"const int ExcelMaxCol = 16384;\nvar (startCol, startRow) = ExcelHandler.ParseCellReference(startCell.ToUpperInvariant());\nlong endCol = (long)ExcelHandler.ColumnNameToIndex(startCol) + maxCols - 1;\nif (endCol > ExcelMaxCol)\n    throw new ArgumentException($\"Import would reach column {endCol} (max {ExcelMaxCol}/XFD).\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["excel","import","validation","dos-hardening","bounds"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}