Repository navigation
Make cut and paste a move: references follow the moved cells (#51) - #236
Conversation
A cut was a copy followed by a clear. A formula that read a cut cell went on reading the now empty one and showed 0, and the cut formula itself was shifted as a copy would be. Pasting a cut now rewrites every reference into the cut block, on every sheet and in every range name, to point at where it landed. The moved formulas are written unshifted, keeping their references to cells outside the block (with the source sheet's name when they move to another sheet). A range follows only when all of it was cut. The source is emptied before the block is written, so a block moved onto part of itself empties what it left instead of keeping it. A cut under a filter moves only the rows it took. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pmWZsbmugfpqtYazrzfjj
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pmWZsbmugfpqtYazrzfjj
…es (#51) Checked in real Excel: with F1 = =H1, cutting D1 and pasting it on H1 turns F1 into #REF! while E1 = =D1*2 follows to H1. A single-cell reference to a cell the pasted block covered now becomes #REF!, with its sheet name dropped as Excel drops it. A range reaching into the landing area is left as it was, since that has not been checked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pmWZsbmugfpqtYazrzfjj
# Conflicts: # README.en.md # README.md # public/screenshots/27-landing-stats.png # public/screenshots/en/27-landing-stats.png # public/screenshots/screenshots.json # public/social-preview.png # src/app/opengraph-image.tsx # src/i18n/en.ts # src/i18n/th.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pmWZsbmugfpqtYazrzfjj
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
PO review — merged at Verify (local, full): green — 2018 tests, mutants 32/32, a11y 121, e2e 59. CI 17/17 green on the same head. Tried as a user on a production build (keyboard Ctrl+X / Ctrl+V, 1280), against what the owner checked in Microsoft Excel this morning:
Limits written in the README, accepted: a range that only partly overlaps the paste area stays where it was, and the source cells keep their format after the move (as Pre-existing, not this PR: a second Ctrl+V after a cut pastes the cut text again from the system clipboard. Nothing is lost; opened as #237 (sev:low, backlog). Hold set left: #235 → #219 → #59. Generated by Claude Code |
What this changes
Closes #51. Next in the sprint-final queue: #219 → #59.
The bug: a cut and paste was a copy followed by a clear. A formula that read a cut cell went on reading the now-empty one and showed
0without a word, and the cut formula itself was shifted the way a copy shifts. In Excel a cut and paste is a move.The fix:
$A$1references too, since a move follows the cell. This is the newformulaEngine/moveRefs.ts, run across the workbook bymoveRefsInWorkbook.placeMovedBlockwrites them as they were, rewriting only references into the block itself.=A1*2moved from B1 to C5 stays=A1*2. A block that refers to itself still does at its new place.=SUM(G1:G3)leaves the formula as it was).A1on the sheet it left becomesSheet2!D1;=Sheet1!A10on Sheet2 becomes=Sheet2!D1when A10 moves to Sheet2!D1, as Excel writes it (checked);Sheet1!C1.mainan overlapping move cleared nothing, so moving A1:A3 to A2:A4 left the old value in A1. Now A1 is empty and references move once.#REF!, as in Excel (checked: with F1 ==H1, cutting D1 onto H1 turns F1 into#REF!while E1 ==D1*2follows to=H1*2). A range reaching into the landing area is left as it was, since that has not been checked.Reproduced on
mainfirstThe steps are the issue's: A1 =
5, B1 ==A1*2.main=A1*2, shows0=D1*2, shows10=D1*2, shows10=B5*2=A1*2=A1*2=B1+…(empty)=C5+…SUM(A1:A3)→SUM(A2:A4)$A$1$G$7=H1, D1 cut onto H1=H1, reads the pasted 5=#REF!#REF!(checked)How it was verified
npm run verify(all ten gates): all ten gates green on968507d. The current heada314bbdcarries that tree unchanged; it only adds the merge ofmain7060a7d, which holds the same files.store/cutMove.test.ts(new, 8), through the same store actions Ctrl+X and Ctrl+V call:formulaEngine/moveRefs.test.ts(new, 7):$kept;#REF!for a cell the block landed on, with a range into it left alone;main'ssheetStore.ts, 7 of the 8 store tests fail. The copy test passes on both, as it should.cutAcrossSheets.test.ts([area:ui] Cut บนชีตหนึ่งแล้ววางอีกชีต ลบข้อมูลของชีตปลายทาง · Cut on one sheet and paste on another erases cells on the destination sheet (sev:critical) #41),filteredSelection.test.ts([area:ui] Delete / copy / Ctrl+Enter ทำงานกับแถวที่ถูกกรองซ่อนไว้ด้วย · Delete, copy and Ctrl+Enter act on rows hidden by a filter (sev:high) #50) andliveWriteRefused.test.ts([area:live-data] Pasting over a live-data cell is accepted and announced, then the next refresh wipes it without a word #232).5, B1 ==A1*2, C1 ==B1+1.=D1*2and shows10.=D1*2(not shifted), and C1 follows it to=C5+1and shows11.moveRefs.tsas the third;For PO: checked in Excel, and what is not done
The owner checked three cases in real Excel desktop (2026-10-05), and this PR matches all three:
#REF!for a reference to a cell the paste covered;=Sheet2!D1across sheets.Still not done, and written into the README as limits:
moveRefs.tsis not incheck:mutants' target list. Adding it would change which mutants the pinned seed draws, so I left the list alone. Say if you want it added in its own PR.The branch
This is the session's branch
claude/new-session-m6mehm. The work was written on a local branch on top of #232, because both changecutSelection/pasteAtSelection, withmain7060a7d(#234) merged in.🤖 Generated with Claude Code
https://claude.ai/code/session_013pmWZsbmugfpqtYazrzfjj
Generated by Claude Code