feat(sheet): merged cells#352
Conversation
Two new ops (mergeCells/unmergeCells, carrying the clearRange rectangle) with Excel absorb semantics: merging over existing merges swallows them; unmerge drops every intersecting range. Non-anchor cell content is kept (hidden by the view) so unmerge restores it. Structural row/col ops shift merges like cells: insert inside grows, delete shrinks, fully deleted or 1x1-collapsed merges drop. Transform shifts the rectangle like clearRange; a rebase past a concurrent delete may collapse a merge to 1x1, which Apply treats as a no-op instead of an error. Client mirror in workbookState/transform, view renders the anchor with rowSpan/colSpan and hides covered tds, arrow navigation snaps onto and steps over merges, ribbon Alignment group gains a merge/unmerge toggle. xlsx import/export round-trips merges via excelize MergeCell. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
PR Summary by Qodofeat(sheet): merged cells end-to-end (ops, model, UI, xlsx)
AI Description
Diagram
High-Level Assessment
Files changed (18)
|
Code Review by Qodo
1.
|
qodo: the exclusive merge end was shifted with the >= insert rule, so inserting a row/col exactly after the merge expanded it. New shiftEnd (Go + TS mirror) keeps an exclusive bound in place when the insert index equals it; delete clamping is unchanged. Also refreshes the stale xlsx Import/Export doc comments that still claimed merges are skipped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What
Merged cells for the collaborative spreadsheet, end to end:
Model / ops (Go + TS mirror) —
Sheet.Merges(top-left anchor → span) plus two ops,mergeCells/unmergeCells, carrying the same rectangle asclearRange. Excel semantics: merging over existing merges absorbs them; unmerge drops every intersecting range. Non-anchor cell content is kept (hidden by the view), so unmerge restores it — no data loss.Structural interplay — insert/delete rows/cols shift merges like cells: an insert inside a merge grows it, a delete shrinks it, merges fully inside a deleted band (or collapsed to 1x1) are dropped.
Transformshifts the op rectangle likeclearRange; a rebase past a concurrent delete can collapse amergeCellsop to 1x1, whichApplytreats as a converging no-op instead of an error.View — the anchor td gets
rowSpan/colSpan, covered tds godisplay:none; arrow-key navigation snaps onto merge anchors and steps over the merged block. Ribbon Alignment group gains a merge/unmerge toggle (the editor picks the direction: any merge intersecting the selection → unmerge).xlsx — merges round-trip through import/export via excelize
MergeCell/GetMergeCells.Tests
sheet_merge.spec.ts, live 3/3): merge renders colspan/rowspan + hides covered cells + unmerge restores content; merge reaches a second client and survives reload; insert-row-above shifts the merge. All 31 sheet specs green.Out of scope
Selection auto-expansion to full merges on drag (Excel behavior) — navigation snapping covers the common path; merge-aware sort/fill.
🤖 Generated with Claude Code