{"record":{"id":"d578eb5040508073","repo":"iOfficeAI/OfficeCLI","slug":"sheet-not-found-shpsheetname","errorCode":null,"errorMessage":"Sheet not found: {shpSheetName}","messagePattern":"Sheet not found: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Drawings.cs","lineNumber":576,"sourceCode":"        // DEFERRED(xlsx/picture-anchor-mode) P12: enumerate all anchor\n        // kinds (twoCell / oneCell / absolute) when counting picture slots.\n        var picAnchors = picDrawingsPart.WorksheetDrawing\n            .Elements<OpenXmlElement>()\n            .Where(a => (a is XDR.TwoCellAnchor || a is XDR.OneCellAnchor || a is XDR.AbsoluteAnchor)\n                && a.Descendants<XDR.Picture>().Any())\n            .ToList();\n        var picIdx = PathIndex.FromArrayIndex(picAnchors.IndexOf(anchor));\n\n        return $\"/{picSheetName}/picture[{picIdx}]\";\n    }\n\n    private string AddShape(string parentPath, string type, InsertPosition? position, Dictionary<string, string> properties)\n    {\n        var index = position?.Index;\n        var shpSegments = parentPath.TrimStart('/').Split('/', 2);\n        var shpSheetName = shpSegments[0];\n        var shpWorksheet = FindWorksheet(shpSheetName)\n            ?? throw new ArgumentException($\"Sheet not found: {shpSheetName}\");\n\n        // CONSISTENCY(ole-width-units): accept `anchor=B2:F7` as a cell\n        // range (same grammar as OLE's anchor=), alongside the legacy\n        // x/y/width/height (column/row units) form. When both are\n        // supplied, warn and let anchor= win — it defines the full\n        // rectangle, so width/height are ambiguous.\n        // CONSISTENCY(ref-alias): `ref=<cell>` maps to single-cell\n        // anchor `<cell>:<cell>`, matching cell/comment/table which\n        // accept `ref=` as the placement address. Explicit `anchor=`\n        // wins if both are given.\n        if (!properties.ContainsKey(\"anchor\")\n            && properties.TryGetValue(\"ref\", out var shpRefProp)\n            && !string.IsNullOrWhiteSpace(shpRefProp))\n        {\n            var refTrim = shpRefProp.Trim();\n            if (!refTrim.Contains(':'))\n            {\n                // Single-cell ref (e.g. \"B2\"): expand to a 1x1 cell","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Drawings.cs#L558-L594","documentation":"Thrown by AddShape when the first segment of the parent path (the sheet name) does not match any worksheet in the workbook. FindWorksheet does a case-insensitive lookup against GetWorksheets() and returns null, which the null-coalescing ?? operator converts into this ArgumentException. It is a pure input-validation failure: no file mutation happens before the throw. The same guard exists on the sparkline path (error 545) and most other drawing add handlers.","triggerScenarios":"Calling the `add` command with a shape/table type and a parent path whose leading segment names a non-existent sheet, e.g. `add /SheetX shape ...` when the workbook only contains `Sheet1`. Also fires when the sheet was renamed, the wrong file was opened, or the path is malformed (empty leading segment).","commonSituations":"Typos or casing/whitespace in the sheet name on the command line; sheet renamed between sessions; script operating on a template that has a different sheet layout; copied command from another workbook without adjusting the sheet name.","solutions":["List the actual sheets with the tool's sheet-listing command and copy the exact name (FindWorksheet is case-insensitive, but trailing spaces and exact spelling matter).","Correct the leading path segment to match an existing sheet, e.g. `/Sheet1` instead of `/SheetX`.","If scripting, resolve the sheet name dynamically from the workbook before building the path instead of hard-coding it."],"exampleFix":"// before\nadd ./book.xlsx /SalesData shape --type rectangle --anchor B2:F7\n// after\nadd ./book.xlsx /Sheet1 shape --type rectangle --anchor B2:F7","handlingStrategy":"validation","validationCode":"// Resolve the sheet against the workbook before building the path.\n// FindWorksheet is case-insensitive; mirror that here.\nvar sheets = GetWorksheetNames(workbook); // your enumeration\nif (!sheets.Any(s => s.Equals(sheetName, StringComparison.OrdinalIgnoreCase)))\n    throw new InvalidOperationException(\n        $\"Sheet '{sheetName}' not found. Available: {string.Join(\", \", sheets)}\");","typeGuard":"static bool SheetExists(WorkbookPart wbp, string sheetName)\n    => wbp.Workbook.Sheets.Elements<Sheet>()\n        .Any(s => s.Name.Value.Equals(sheetName, StringComparison.OrdinalIgnoreCase));","tryCatchPattern":"try { handler.Add(...); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Sheet not found\"))\n{\n    // re-resolve sheet list, surface to user, do not retry blindly\n    Console.Error.WriteLine(ex.Message);\n}","preventionTips":["Never hard-code sheet names in scripts; resolve them from the workbook at runtime.","Validate the path's leading segment against the sheet list before invoking add.","Treat a sheet rename as a breaking change and update dependent scripts."],"tags":["excel","sheet-not-found","input-validation","ooxml","drawing"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}