Skip to main content

Module embedded_object

Module embedded_object 

Source
Expand description

Charts and slicers via spreadsheets.batchUpdate (issue #1797, ADR-0081 §3).

Extended by issue #1837 with move-chart/move-slicer (updateEmbeddedObjectPosition) and update-chart-border (updateEmbeddedObjectBorder).

One module for both, per the issue’s own framing: a slicer is an embedded object exactly like a chart, and both are removed by the same deleteEmbeddedObject request, addressed by objectId alone with no discriminator naming which kind it is.

Gate. Every mutating verb here — including both deletes — reaches DriveOperation::SheetsStructure. ADR-0081 §3 settles this the same way unmerge-cells/clear-data-validation were settled in ADR-0078: a chart or slicer is a property of the sheet, not the sheet’s grid data, one level further out than a merge or a validation rule but the same kind of thing. The unrecoverability is real, so delete-chart/ delete-slicer read back and report the object’s spec — type, title, anchor position — before ever sending the request, in both --dry-run and the real run’s drivemutation record (the discarded_cells treatment applied to an object instead of a value). list-charts/ list-slicers are read-only and ungated, like list-protections.

Chart subset (v1). basicChart restricted to chartType ∈ {COLUMN, BAR, LINE, AREA, SCATTER} and pieChart — the issue’s own chosen first cut. Every other chart type (bubble, candlestick, org, histogram, waterfall, treemap, scorecard, data-source) is a documented cut, not a silent gap.

update-chart’s crux: no field mask. updateChartSpec replaces a chart’s entire ChartSpec, unlike every other update* request in this crate. merge_chart_spec fetches the existing spec, refuses it outright if it isn’t one of the two supported kinds (rather than silently discarding a histogram’s configuration), refuses a basic↔pie switch (the two unions carry domain/series too differently to convert), and otherwise applies only the flags the caller actually set — preserving everything else, including every field this crate doesn’t model, via each spec type’s #[serde(flatten)] extra map. update-slicer is the opposite case: updateSlicerSpec does take a field mask, so it only ever names the fields actually set.

move-chart/move-slicer’s crux: the field mask is rooted at overlayPosition, not newPosition. updateEmbeddedObjectPosition’s own rule is that “the root newPosition.overlayPosition is implied and should not be specified” — the one request in this file whose mask isn’t rooted at the request’s own payload field (cf. update-slicer’s mask, rooted at spec). overlay_position_update builds both the position and the mask together so the two can’t drift apart; a resize-only move (no --anchor) still carries the object’s current anchor forward on the wire, since OverlayPosition.anchor_cell is a required field there, even though the mask never names it. A chart on its own sheet has no overlay position to carry forward, so moving it onto a grid requires --anchor; --new-sheet sends no fields at all.

update-chart-border is colour-only. EmbeddedObjectBorder models colorStyle alone — no style, no width — so --clear sends an empty border (border: {}) with the same "colorStyle" mask a set does.

Confirmed live (issue #1929). A chart that never had its border touched reads back with no border field at all. But --clear does not return a chart to that state: it reads back with border present and an all-omitted colorStyle.rgbColor — proto3 dropping every zero-valued channel. Sending an explicit --color 000000 (pure black) reads back byte-for-byte identical to a clear: {"colorStyle": {"rgbColor": {}}} either way. There is no second field to break the tie, so “cleared” and “explicit black” are genuinely indistinguishable from a read alone — [describe_border_color] reports that ambiguity rather than guessing. Whether the Sheets UI actually paints a visible black border after --clear was not checked (this crate cannot inspect the rendered UI); what’s confirmed is only the wire shape.

Documented cuts, matching this feature’s general stance: COMBO/STEPPED_AREA basic charts (need a per-series type this crate doesn’t model), and condition-based slicer filter criteria (FilterCriteria supports hiddenValues only, the same cut filter.rs makes).

Shape mirrors filter.rs: compose/validate, resolve against a freshly-fetched workbook, gate, dry-run, mutate, log.

Structs§

EmbeddedObjectOptions
Per-call options.
EmbeddedObjectOutcome
The full outcome of one attempt.
EmbeddedObjectSummary
A chart or slicer’s identifying details, as reported in a preview or a completed result — the “type, title or id, anchor position” ADR-0081 §3 requires before an unrecoverable delete.

Enums§

EmbeddedObjectResult
What happened (or, under --dry-run, would happen).
EmbeddedObjectVerb
Which mutation to perform.

Functions§

charts_from_workbook
Extracts every chart’s summary from an already-fetched workbook, for list-charts.
describe
Renders an outcome as human-readable text.
describe_lines
Renders an outcome as its individual lines, none of which contains a newline — see structure.rs::describe_lines for why this shape exists.
embedded_object
Runs one embedded-object mutation, logging every attempt that isn’t a dry run.
slicers_from_workbook
Extracts every slicer’s summary from an already-fetched workbook, for list-slicers. See charts_from_workbook’s doc comment.