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§
- Embedded
Object Options - Per-call options.
- Embedded
Object Outcome - The full outcome of one attempt.
- Embedded
Object Summary - 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§
- Embedded
Object Result - What happened (or, under
--dry-run, would happen). - Embedded
Object Verb - 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_linesfor 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. Seecharts_from_workbook’s doc comment.