{"record":{"id":"de3fa37f643ce8bf","repo":"iOfficeAI/OfficeCLI","slug":"sparkline-requires-location-or-cell-property","errorCode":null,"errorMessage":"Sparkline requires 'location' (or 'cell') property (e.g. F1)","messagePattern":"Sparkline requires 'location' \\(or 'cell'\\) property \\(e\\.g\\. F1\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Drawings.cs","lineNumber":977,"sourceCode":"        var index = position?.Index;\n        var spkSegments = parentPath.TrimStart('/').Split('/', 2);\n        var spkSheetName = spkSegments[0];\n        var spkWorksheet = FindWorksheet(spkSheetName)\n            ?? throw new ArgumentException($\"Sheet not found: {spkSheetName}\");\n\n        // CONSISTENCY(canonical-key): 'location'/'dataRange' are canonical;\n        // 'cell'/'range'/'data' retained as legacy aliases.\n        // R12a: also accept the host cell from the parent path tail\n        // (e.g. `add /Sheet1/F1 sparkline --prop dataRange=A1:E1`), mirroring\n        // how cell/cf Add derive their target from the path. Explicit\n        // location=/cell= still wins.\n        var spkPathTail = spkSegments.Length > 1\n            && Regex.IsMatch(spkSegments[1], @\"^[A-Z]+\\d+$\", RegexOptions.IgnoreCase)\n            ? spkSegments[1].ToUpperInvariant() : null;\n        var spkCell = properties.GetValueOrDefault(\"location\")\n            ?? properties.GetValueOrDefault(\"cell\")\n            ?? spkPathTail\n            ?? throw new ArgumentException(\"Sparkline requires 'location' (or 'cell') property (e.g. F1)\");\n        var spkRange = properties.GetValueOrDefault(\"dataRange\")\n            ?? properties.GetValueOrDefault(\"datarange\")\n            ?? properties.GetValueOrDefault(\"range\")\n            ?? properties.GetValueOrDefault(\"data\")\n            ?? throw new ArgumentException(\"Sparkline requires 'dataRange' (or 'range'/'data') property (e.g. A1:E1)\");\n\n        // OOXML xm:sqref is ST_Sqref (bare cell address, no sheet prefix —\n        // sheet is implied by the parent worksheet). Excel silently drops the\n        // entire <extLst> on load if sqref carries a sheet prefix.\n        spkCell = NormalizeSparklineSqref(spkCell, spkSheetName);\n        // A location that is not a real cell reference (\"XYZ\", empty) wrote a\n        // semantically dead <xne:sqref> anchor with no warning; validate the\n        // final sqref like every other cell-ref input.\n        if (string.IsNullOrWhiteSpace(spkCell)\n            || !Regex.IsMatch(spkCell, @\"^\\$?[A-Za-z]{1,3}\\$?\\d+(:\\$?[A-Za-z]{1,3}\\$?\\d+)?$\"))\n            throw new ArgumentException(\n                $\"Invalid sparkline 'location': '{spkCell}'. Expected a cell reference like F1 (or a range like F1:F5).\");\n        ParseCellReference(spkCell.Replace(\"$\", \"\").Split(':')[0]);","sourceCodeStart":959,"sourceCodeEnd":995,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Drawings.cs#L959-L995","documentation":"Thrown by AddSparkline when no sparkline host-cell location can be resolved. The cell comes from `location=`, then the legacy alias `cell=`, then an optional A1-style tail on the parent path (e.g. `/Sheet1/F1`). If all three are absent the ?? chain throws. The location is required because OOXML xm:sqref must anchor the sparkline to a concrete cell.","triggerScenarios":"Calling `add /Sheet1 sparkline --prop dataRange=A1:E1` with no `location=`/`cell=` and no path tail; or misspelling the key (`loc=`, `target=`). The canonical key is `location`; `cell` is the legacy alias.","commonSituations":"Forgetting the host cell (a sparkline lives IN a cell, not just over a data range); using an unsupported alias; assuming the dataRange's first cell becomes the host automatically (it does not).","solutions":["Add `--prop location=F1` (the cell where the sparkline will render).","Alternatively supply `--prop cell=F1` (legacy alias) or put the cell in the path: `add ./book.xlsx /Sheet1/F1 sparkline --prop dataRange=A1:E1`."],"exampleFix":"// before\nadd ./book.xlsx /Sheet1 sparkline --prop dataRange=A1:E1\n// after\nadd ./book.xlsx /Sheet1 sparkline --prop location=F1 --prop dataRange=A1:E1","handlingStrategy":"validation","validationCode":"// Resolve the sparkline host cell with the same precedence the handler uses.\nvar hostCell = props.GetValueOrDefault(\"location\")\n    ?? props.GetValueOrDefault(\"cell\")\n    ?? pathTailCell;\nif (string.IsNullOrWhiteSpace(hostCell))\n    throw new InvalidOperationException(\"Sparkline requires a host cell (location= or path tail)\");","typeGuard":"static bool HasSparklineLocation(IReadOnlyDictionary<string,string> p, string? pathTail)\n    => !string.IsNullOrWhiteSpace(p.GetValueOrDefault(\"location\"))\n    || !string.IsNullOrWhiteSpace(p.GetValueOrDefault(\"cell\"))\n    || !string.IsNullOrWhiteSpace(pathTail);","tryCatchPattern":"try { handler.AddSparkline(...); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"requires 'location'\"))\n{ /* prompt for the host cell address */ }","preventionTips":["Always specify location= (or put the cell in the path) — a sparkline must live in a cell.","Use the canonical key `location`; treat `cell` as a legacy alias only."],"tags":["excel","sparkline","missing-property","cell-reference","input-validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}