{"record":{"id":"8ab12f8af0d89930","repo":"iOfficeAI/OfficeCLI","slug":"sheet-not-found-olesheetname-ole-must-be-added","errorCode":null,"errorMessage":"Sheet not found: {oleSheetName}. ole must be added under a sheet: add-part <file> /<SheetName> --type ole","messagePattern":"Sheet not found: (.+?)\\. ole must be added under a sheet: add-part <file> /<SheetName> --type ole","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.cs","lineNumber":1272,"sourceCode":"            }\n\n            case \"ole\":\n            {\n                // Verbatim OLE carrier for dump→batch round-trip. Mirrors the\n                // pptx add-part ole contract (pinned rIds + base64 payloads)\n                // but is all-in-one: Excel's OLE anatomy spans the worksheet\n                // (<oleObjects> child + embed/icon rels), the VML drawing\n                // (anchor shape) and <legacyDrawing>, all of which must stay\n                // consistent — so the handler wires everything here instead\n                // of leaving XML splicing to a companion raw-set.\n                // Props: rid + data (+content-type/extension) = payload part;\n                // icon-rid + icon-data (+icon-content-type) = objectPr image;\n                // vml-shape = the <v:shape> anchor XML verbatim;\n                // object-xml = the <oleObjects> CHILD element verbatim\n                // (mc:AlternateContent or bare oleObject, pinned rIds inside).\n                var oleSheetName = parentPartPath.TrimStart('/');\n                var oleWs = FindWorksheet(oleSheetName)\n                    ?? throw new ArgumentException(\n                        $\"Sheet not found: {oleSheetName}. ole must be added under a sheet: add-part <file> /<SheetName> --type ole\");\n                properties ??= new Dictionary<string, string>();\n                var oleRid = properties.GetValueOrDefault(\"rid\")\n                    ?? throw new ArgumentException(\"'rid' property is required for ole (pinned payload relationship id)\");\n                var oleDataB64 = properties.GetValueOrDefault(\"data\")\n                    ?? throw new ArgumentException(\"'data' property is required for ole (base64 payload bytes)\");\n                var oleObjectXml = properties.GetValueOrDefault(\"object-xml\")\n                    ?? throw new ArgumentException(\"'object-xml' property is required for ole (verbatim oleObjects child element)\");\n                byte[] oleBytes;\n                try { oleBytes = Convert.FromBase64String(oleDataB64); }\n                catch (FormatException) { throw new ArgumentException(\"add-part ole: 'data' is not valid base64\"); }\n\n                var oleCt = properties.GetValueOrDefault(\"content-type\")\n                    ?? \"application/vnd.openxmlformats-officedocument.oleObject\";\n                var oleExt = properties.GetValueOrDefault(\"extension\") ?? \".bin\";\n                if (!oleExt.StartsWith('.')) oleExt = \".\" + oleExt;\n\n                // Kind comes from the dump (source part type), because content","sourceCodeStart":1254,"sourceCodeEnd":1290,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.cs#L1254-L1290","documentation":"Thrown by AddPart for the 'ole' part type — an all-in-one carrier that wires the worksheet's <oleObjects> child, the payload embed rel, the VML anchor shape, and the <legacyDrawing>. OLE anatomy is spread across the worksheet and its VML drawing, so the parent path must resolve to the worksheet that will host the <oleObjects> element.","triggerScenarios":"AddPart(parentPartPath, \"ole\", ...) where parentPartPath (after TrimStart('/')) does not name an existing worksheet — wrong path, renamed sheet, out-of-range sheet index, or empty.","commonSituations":"Replaying a dump after the host sheet was renamed/deleted; passing the OLE part path (e.g. \"/xl/embeddings/oleObject1.bin\") instead of the sheet name; targeting a chart sheet that has no worksheet part.","solutions":["Pass the host sheet display name as the parent path (e.g. \"/Sheet1\").","List worksheets and confirm the name before the call.","Re-dump against the current file to keep names in sync.","If the original sheet is gone, retarget the OLE to a surviving sheet."],"exampleFix":"// before\nhandler.AddPart(\"/xl/embeddings/oleObject1.bin\", \"ole\", props);\n// after\nhandler.AddPart(\"/Sheet1\", \"ole\", props);","handlingStrategy":"validation","validationCode":"var name = parentPartPath.TrimStart('/');\nif (!handler.GetWorksheets().Any(w => w.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))\n    /* fix the parent path before calling AddPart */","typeGuard":"static bool SheetResolves(ExcelHandler h, string parentPartPath) =>\n    h.GetWorksheets().Any(w => w.Name.Equals(\n        parentPartPath.TrimStart('/'), StringComparison.OrdinalIgnoreCase));","tryCatchPattern":"try { handler.AddPart(parentPartPath, \"ole\", props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"ole must be added under a sheet\"))\n{ /* reconcile sheet name, retry with /SheetName */ }","preventionTips":["Pass the host sheet name, not the OLE embeddings part path.","Refresh the dump before replay so sheet names match.","Avoid targeting chart/dialog sheets that have no worksheet part."],"tags":["excel","openxml","add-part","ole","sheet-lookup"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}