{"record":{"id":"61e06e6338a47f19","repo":"iOfficeAI/OfficeCLI","slug":"source-sheet-relationship-does-not-resolve-to-a-wo","errorCode":null,"errorMessage":"Source sheet relationship does not resolve to a WorksheetPart","messagePattern":"Source sheet relationship does not resolve to a WorksheetPart","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/PivotTableHelper.Readback.cs","lineNumber":411,"sourceCode":"            newRef = parts[1].Trim();\n        }\n        else\n        {\n            newSheetName = existingWsSource.Sheet?.Value ?? \"\";\n            newRef = newSourceSpec;\n        }\n\n        // Locate the source worksheet via the workbook part.\n        var workbookPart = pivotPart.GetParentParts().OfType<WorksheetPart>().FirstOrDefault()\n            ?.GetParentParts().OfType<WorkbookPart>().FirstOrDefault()\n            ?? throw new InvalidOperationException(\"Workbook part not reachable from pivot table part\");\n        var sheetEntry = workbookPart.Workbook?.Sheets?.Elements<Sheet>()\n            .FirstOrDefault(s => s.Name?.Value == newSheetName)\n            ?? throw new ArgumentException($\"Source sheet not found: {newSheetName}\");\n        if (sheetEntry.Id?.Value is not string srcRelId)\n            throw new InvalidOperationException(\"Source sheet has no relationship id\");\n        var sourceWsPart = workbookPart.GetPartById(srcRelId) as WorksheetPart\n            ?? throw new InvalidOperationException(\"Source sheet relationship does not resolve to a WorksheetPart\");\n\n        // Re-read source data from the new range.\n        var (headers, columnData, _) = ReadSourceData(sourceWsPart, newRef);\n        if (headers.Length == 0)\n            throw new ArgumentException(\"Source range has no data\");\n        if (columnData.Count == 0 || columnData[0].Length == 0)\n            throw new ArgumentException(\"Source range has no data rows\");\n\n        // R15-2: Before mutating any cache/pivot state, validate that existing\n        // row/col/value/filter field references still fit inside the new\n        // (possibly narrower) header list. A silent drop or index clamp here\n        // would leave the DataFields pointing past the rendered columnData,\n        // crashing RenderPivotIntoSheet with ArgumentOutOfRangeException.\n        // Prefer strict error over data loss: user must explicitly restate the\n        // affected axes in the same Set call if they intended to drop them.\n        var newFieldCount = headers.Length;\n        var existingPivotDef = pivotPart.PivotTableDefinition;\n        if (existingPivotDef != null)","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/PivotTableHelper.Readback.cs#L393-L429","documentation":"Thrown when the sheet's relationship id resolves via GetPartById but the returned OpenXmlPart is not a WorksheetPart (the 'as WorksheetPart' cast yields null). This happens when the named 'sheet' is actually a chartsheet or another non-worksheet part type, so the pivot source cannot read cell data from it.","triggerScenarios":"Setting source= to a range on a chartsheet (ChartsheetPart) instead of a real worksheet. Or a workbook where the relationship target for the sheet was changed to a non-worksheet part type through corruption or aggressive manipulation.","commonSituations":"Workbook contains chart sheets; user picks the wrong tab name that happens to be a chartsheet; a third-party tool repackaged the workbook and mislabeled part types.","solutions":["Point the pivot source at a range that lives on an actual worksheet, not a chartsheet.","Check that the sheet tab you are referencing is a worksheet type (has a grid of cells), not a chart-only sheet.","If the file is corrupt, re-save in Excel/LibreOffice to rebuild part types."],"exampleFix":"// before — 'Chart1' is a chartsheet, not a worksheet\nSet pivot source=Chart1!A1:D10\n// after — use the data worksheet\nSet pivot source=Data!A1:D10","handlingStrategy":"validation","validationCode":"// Confirm the target sheet resolves to a real WorksheetPart before setting source\nvar sheetEntry = workbookPart.Workbook?.Sheets?.Elements<Sheet>()\n    .FirstOrDefault(s => s.Name?.Value == targetSheetName);\nif (sheetEntry?.Id?.Value is string relId)\n{\n    var part = workbookPart.GetPartById(relId);\n    if (part is not WorksheetPart)\n        throw new InvalidOperationException($\"'{targetSheetName}' is not a worksheet (got {part?.GetType().Name}); use a data worksheet.\");\n}","typeGuard":"static bool IsWorksheet(WorkbookPart wbPart, string sheetName) =>\n    wbPart.Workbook?.Sheets?.Elements<Sheet>()\n        .FirstOrDefault(s => s.Name?.Value == sheetName)?.Id?.Value is string rid\n    && wbPart.GetPartById(rid) is WorksheetPart;","tryCatchPattern":null,"preventionTips":["Never point a pivot source at a chart sheet — pivots require cell data.","Verify the tab type (worksheet vs chartsheet) before referencing it.","If a workbook has chart sheets, distinguish them from data worksheets by name."],"tags":["pivot","excel","ooxml","chartsheet","worksheet","set-property"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}