iOfficeAI/OfficeCLI · error · ArgumentException

Sheet has no data

Error message

Sheet has no data

What it means

Thrown for a row/column element move when the source worksheet's GetSheet(worksheet).GetFirstChild<SheetData>() is null. SheetData is the container that holds <Row>/<Cell> elements; a worksheet lacking it has never had data written (a freshly-created or empty sheet). The handler cannot move a row/col out of a sheet that has no data structure.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.cs:271

                {
                    var lid = dn.LocalSheetId?.Value;
                    if (lid == null || lid >= preMoveOrder.Count) continue;
                    var newIdx = postMoveOrder.IndexOf(preMoveOrder[(int)lid.Value]);
                    if (newIdx >= 0 && newIdx != lid.Value) dn.LocalSheetId = (uint)newIdx;
                }
            }

            // Mark the document modified so Dispose flushes it. Without this,
            // a `using (h) h.Move(...)` (no explicit Save) is silently dropped
            // by the !Modified byte-preserving discard path in Dispose.
            Modified = true;
            workbook.Save();
            return $"/{sheetName}";
        }

        var elementRef = segments[1];
        var sheetData = GetSheet(worksheet).GetFirstChild<SheetData>()
            ?? throw new ArgumentException("Sheet has no data");

        // Determine the target sheet's SheetData. The result path is built from
        // the resolved target SHEET (below), NOT the raw --to: a row/col/cell
        // lives directly under a sheet, so a non-sheet --to like /Sheet1/row[2]
        // must not leak into the result path (it used to produce a doubled
        // /Sheet1/row[2]/row[3]). Only the sheet segment of --to is meaningful.
        SheetData targetSheetData;
        if (string.IsNullOrEmpty(targetParentPath))
        {
            targetSheetData = sheetData;
        }
        else
        {
            var tgtSegments = targetParentPath.TrimStart('/').Split('/', 2);
            var tgtWorksheet = FindWorksheet(tgtSegments[0])
                ?? throw new ArgumentException($"Target sheet not found: {tgtSegments[0]}");
            targetSheetData = GetSheet(tgtWorksheet).GetFirstChild<SheetData>()
                ?? throw new ArgumentException("Target sheet has no data");

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Target a sheet that actually contains rows (check the sheet is non-empty first).
  2. Populate the sheet (Add/Set a row) before attempting a row/col move from it.
  3. If you meant to move the whole sheet, drop the '/row[N]' segment so the sheet-reorder path runs instead.

Example fix

// before
h.Move("/Empty/row[1]", "/Data", null); // Empty has no <sheetData>
// after
h.Move("/Data/row[1]", "/Report", null); // move from a populated sheet
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the sheet actually has rows via the public query surface.
var node = handler.Get(sourcePath.TrimStart('/').Split('/', 2)[0], depth: 2);
if (!node.Children.Any(c => c.Type == "row"))
    throw new InvalidOperationException("Source sheet has no data to move");

Try / catch

try { handler.Move("/Sheet/row[1]", target, pos); }
catch (ArgumentException ex) when (ex.Message == "Sheet has no data")
{ /* source sheet is empty; pick a populated sheet or populate it first */ }

Prevention

When it happens

Trigger: Move("/Blank/row[1]") on a sheet that was created but never populated; operating on a template sheet with only dimensions/defaults but no <sheetData>; a sheet whose data was fully removed.

Common situations: Newly-added sheet via Add before any Set/insert; sheet from a minimal template; expecting rows that exist only conceptually (used range) rather than as stored elements.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/165009b685cb3b18. Report an issue: GitHub.