iOfficeAI/OfficeCLI · error · ArgumentException

Source sheet not found: {newSheetName}

Error message

Source sheet not found: {newSheetName}

What it means

Thrown by RefreshPivotCacheFromSource when re-binding an existing pivot to a new source range via Set source=. The sheet name (parsed from the spec before '!' e.g. 'Sheet1!A1:D10', or the cache's previously-stored sheet name if the spec has no '!') does not match any <Sheet> element in Workbook.Sheets. OOXML registers worksheet tabs there, so the pivot's WorksheetSource.Sheet must resolve to one of those entries by exact name match.

Source

Thrown at src/officecli/Core/PivotTableHelper.Readback.cs:407

        if (newSourceSpec.Contains('!'))
        {
            var parts = newSourceSpec.Split('!', 2);
            newSheetName = parts[0].Trim().Trim('\'', '"').Trim();
            newRef = parts[1].Trim();
        }
        else
        {
            newSheetName = existingWsSource.Sheet?.Value ?? "";
            newRef = newSourceSpec;
        }

        // Locate the source worksheet via the workbook part.
        var workbookPart = pivotPart.GetParentParts().OfType<WorksheetPart>().FirstOrDefault()
            ?.GetParentParts().OfType<WorkbookPart>().FirstOrDefault()
            ?? throw new InvalidOperationException("Workbook part not reachable from pivot table part");
        var sheetEntry = workbookPart.Workbook?.Sheets?.Elements<Sheet>()
            .FirstOrDefault(s => s.Name?.Value == newSheetName)
            ?? throw new ArgumentException($"Source sheet not found: {newSheetName}");
        if (sheetEntry.Id?.Value is not string srcRelId)
            throw new InvalidOperationException("Source sheet has no relationship id");
        var sourceWsPart = workbookPart.GetPartById(srcRelId) as WorksheetPart
            ?? throw new InvalidOperationException("Source sheet relationship does not resolve to a WorksheetPart");

        // Re-read source data from the new range.
        var (headers, columnData, _) = ReadSourceData(sourceWsPart, newRef);
        if (headers.Length == 0)
            throw new ArgumentException("Source range has no data");
        if (columnData.Count == 0 || columnData[0].Length == 0)
            throw new ArgumentException("Source range has no data rows");

        // R15-2: Before mutating any cache/pivot state, validate that existing
        // row/col/value/filter field references still fit inside the new
        // (possibly narrower) header list. A silent drop or index clamp here
        // would leave the DataFields pointing past the rendered columnData,
        // crashing RenderPivotIntoSheet with ArgumentOutOfRangeException.
        // Prefer strict error over data loss: user must explicitly restate the

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Verify the sheet name exists in the workbook with exact spelling and case (sheet names are case-sensitive in OOXML).
  2. If the sheet was renamed, pass the new name explicitly in the source spec: source=NewSheetName!A1:D10.
  3. If you want to keep the same sheet as the existing cache, use the bare-range form source=A1:D10 without a sheet qualifier so it reuses existingWsSource.Sheet.
  4. List workbook sheets first (Get workbook sheets) to confirm the exact tab name before calling Set source=.

Example fix

// before — sheet was renamed from 'Data' to 'Sales'
Set pivot source=Data!A1:F100
// after
Set pivot source=Sales!A1:F100
Defensive patterns

Strategy: validation

Validate before calling

// Before calling Set source=, verify the sheet exists
var sheets = workbookPart.Workbook?.Sheets?.Elements<Sheet>()
    .Select(s => s.Name?.Value)
    .Where(n => n != null)
    .ToHashSet(StringComparer.Ordinal);
var specSheet = sourceSpec.Contains('!')
    ? sourceSpec.Split('!', 2)[0].Trim().Trim('\'', '"').Trim()
    : existingCacheSheetName;
if (sheets == null || !sheets.Contains(specSheet))
    throw new InvalidOperationException($"Sheet '{specSheet}' not found. Available: {string.Join(", ", sheets ?? new HashSet<string>())}");

Prevention

When it happens

Trigger: Calling SetPivotTableProperties with source=Foo!A1:D10 where 'Foo' is not a tab in the workbook. Or calling source=A1:D10 (no sheet qualifier) when the existing cache's stored WorksheetSource.Sheet value is stale because the worksheet was renamed or deleted after the pivot was created.

Common situations: Renaming a worksheet after the pivot was created, leaving a stale sheet name in the cache source; typo in the CLI source= argument (wrong case, trailing space, quote mismatch); copy-pasting a source spec from a different workbook; sheet name contains leading/trailing whitespace that the Trim('\\\'','\"') in the parser does not fully normalize.

Related errors


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