iOfficeAI/OfficeCLI · error · ArgumentException

Target sheet has no data

Error message

Target sheet has no data

What it means

Thrown when the resolved target worksheet (for a cross-sheet row move) has no <sheetData> element. Even though the target sheet exists, it carries no data container, so there is nowhere to insert the moved row. This is the target-side equivalent of 'Sheet has no data'.

Source

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

            ?? 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");
        }

        // Find and move the row
        var rowMatch = Regex.Match(elementRef, @"^row\[(\d+)\]$");
        if (rowMatch.Success)
        {
            var rowIdx = int.Parse(rowMatch.Groups[1].Value);
            // Try ordinal lookup first (Nth row element), then fall back to RowIndex
            var allRows = sheetData.Elements<Row>().ToList();
            var row = (rowIdx >= 1 && rowIdx <= allRows.Count ? allRows[PathIndex.ToArrayIndex(rowIdx)] : null)
                ?? sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex?.Value == (uint)rowIdx)
                ?? throw new ArgumentException($"Row {rowIdx} not found");

            // Resolve --before / --after anchors to a 0-based document-order
            // position in the target sheet. Anchor must be /<TargetSheet>/row[K].
            // Resolved BEFORE removing the moved row so the anchor is found by
            // its current position.
            int? targetIndex = index;

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Populate the target sheet with at least one row before moving into it.
  2. Choose a target sheet that already contains data.
  3. If the target is brand new, seed it with a placeholder row then move.

Example fix

// before
h.Move("/Data/row[1]", "/Fresh", null); // Fresh has no <sheetData>
// after
h.Add("/Fresh", "row", null, new());            // seed so SheetData exists
h.Move("/Data/row[1]", "/Fresh", InsertPosition.AtIndex(1));
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the target sheet already holds data before moving into it.
var tgt = targetParentPath!.TrimStart('/').Split('/', 2)[0];
var node = handler.Get(tgt, depth: 2);
if (!node.Children.Any(c => c.Type == "row"))
    throw new InvalidOperationException("Target sheet has no data; seed it first");

Try / catch

try { handler.Move(src, target, pos); }
catch (ArgumentException ex) when (ex.Message == "Target sheet has no data")
{ /* seed the target with a row, then retry the move */ }

Prevention

When it happens

Trigger: Moving a row into a freshly-created or empty target sheet that was never populated; target sheet whose data was stripped; minimal template sheet used as a destination.

Common situations: Destination created by Add('sheet') but not yet written to; template sheets with only column defaults; exporter that omits <sheetData> on empty sheets.

Related errors


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