Repository navigation
Workbook Links: update linked workbooks from their files, change source, break links, startup prompt (builds on #464 and #829) - #1200
Open
Herr-Enklo wants to merge 16 commits into
Open
Herr-Enklo wants to merge 16 commits into
Herr-Enklo wants to merge 16 commits into
Conversation
…with the link A formula reading another workbook ([1]Prices!B2, '[2]P&L'!A1:B9, a name over such a range) recalculated to #REF!: the externalLink parts were passed through on save but never read. Excel calculates these from the cached copy of the linked cells it saves in the file, as it does whenever the source is closed. On a 4,224-file real-world corpus this was the largest root cause of calculation mismatches. The reader now loads each link's sheet names, cached cells, refresh-error flags and defined names into Workbook::external_books; the lexer reads unquoted [1]Sheet!A1 and [1]!Name; references, linked names and [0]!Name evaluate from that data; the *IF(S) range arguments refuse linked-workbook values and written errors, as Excel does with a closed source; and linked sheets print unquoted when the sheet name allows, so saved formulas keep their text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… prints back References into a linked workbook became value arrays when evaluated, so `@` and implicit intersection took the top-left value (`=@[1]Data!B:B` in row 4 gave the header), ROWS/COLUMNS/INDEX saw the block trimmed to the last cached cell (`ROWS([1]Data!A:A)` = 3), and every lookup rebuilt the whole block. They are now Areas whose sheet number (from LINKED_SHEETS up) stands for the linked workbook and sheet; cells are read from the saved values only when the reference is dereferenced (Evaluator::cell, Evaluator::block_values), and a linked sheet's extent is remembered per pass like a local used range. The printer dropped the quotes from '[1]Jan:Dec'!A1 and the lexer couldn't read [1]Jan:Dec!A1. The lexer now accepts the unquoted MS-XLSX sheet-range form, and the printer quotes a range when either sheet name needs it.
…]Jan:Dec
OFFSET took a reference into a linked workbook as its base and read the
saved link values. Excel errors there while the source is closed: the Enron
West NatGas Prices cells wrap OFFSET('[21]Curve Summary'!...) in ISERROR and
cached the backup value. OFFSET now answers #VALUE! for a linked base, the
answer of the other reference-only parameters given a closed workbook's values.
Renaming a local sheet rewrote the second end of [1]Jan:Dec!A1, which names a
sheet of the linked workbook; rename_sheet and delete_sheet now skip spans
whose first end is in a linked workbook.
Workbook::external_books is behind an Arc, like sheets and preserved parts,
so each edit's workbook clone and the undo history share the link cache.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…[0] is this workbook
…ixes; [0] names stored local; CF/DV refuse other workbooks; paste into another workbook drops [n]
…New Window of the same workbook)
…se as references to another workbook
…ng as new link parts
…link, shown with the file (fixes storytold#804)
…d on write (My%20Files)
… refused, [1]!Rate isn't)
's [n] check storytold#829 was written against an older storytold#464. Its typed references by file name or path (`[Source.xlsx]Sheet1!A1`, `'C:\links\[Source.xlsx]Sheet1'!A1`) were refused by the entry check storytold#464 added since (a bracketed prefix that isn't a link index). The check now lets a typed file through where entry links it (`typed_book`), and linking runs last in `input_to_cell`, so a formula refused for another reason never leaves a new link behind. Conditional formats, data validation and paste still refuse other workbooks. A typed file must look like one (a folder or an extension), so `[-1]Sheet1`, `[ 1]Sheet1` and `[Book2]Sheet1` stay refused as storytold#464's review asked. `[1]!Rate` prints without quotes around `[1]`, and the shown name of a link (`'C:\links\Source.xlsx'!Rate`) is quoted once by the printer, as main now quotes sheet-qualified names itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…inks, startup prompt
The engine side of Data › Queries & Connections › Workbook Links and File › Info › Edit Links
to Files. Every action is a command, reachable from the CLI and MCP:
- data.workbookLinks / data.editLinks list the links (file, path, type, update, status, last
refreshed, formulas using it) and ask the UI for the pane or the dialog.
- data.refreshLinks {link?} (Update Values / Refresh) reads the source workbook with
gridcraft-xlsx: the cells and names this workbook reads from it, including whole columns
trimmed to the source's used range, names used inside linked names, and 3-D spans. A source
saved without values is calculated first. One undo step; dependents recalculate.
- data.checkLinkStatus: OK, Error: Source not found, Error: Worksheet not found, Warning:
Values not updated (the file has other values than the link), Error: Undetermined.
- data.changeLinkSource {link, path} points the link at another file and reads it; onto a file
another link reads, the two links become one.
- data.breakLink {link?}: as observed in Excel, every cell formula that reads the link, also
through a defined name, becomes its value (arrays become the values of their range); names
stay and keep the link. A link nothing names any more is removed and the later [n] move up.
- data.linkStartupPrompt {mode}: userSet / never / always, saved as workbookPr updateLinks
(ECMA-376 ST_UpdateLinks); the default isn't written.
- data.openLinkSource opens the source; data.enableLinkUpdates is the security warning's
Enable Content.
Opening a workbook never reads its links: like Excel, their automatic update is disabled until
Enable Content or Update Values (not at all when the prompt says never). Status and last refresh
are session state (DocState::links). Files are read through Session::link_files, the file system
off wasm; in the browser the commands that read sources are disabled with a reason.
Saving: ExternalBook::kept (replacing storytold#829's `added`) says which link part of the file holds a
link unchanged. Unchanged links are still written back byte for byte; a link added, refreshed or
moved to another source is written from the model in its place, and the part of a removed link
is dropped. Save As rebases relative paths of links written from the model too (storytold#824).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…warning Data gets Excel 365's Queries & Connections group: the Refresh All split button (Refresh All, Refresh, and Refresh Status, Cancel Refresh, Connection Properties… shown disabled), then Queries & Connections, Properties (disabled) and Workbook Links, which is off while the workbook links to no other workbook, as in Excel. Key tip A K now runs Workbook Links (it was Edit Links). Workbook Links opens the task pane: Refresh All, Break All, a search box and a card per linked workbook with its location, status (OK, Warning: Values not updated, Error: Source not found…), last refresh and Refresh, Open Workbook, Change Source… and Break Links. File › Info shows Related Documents › Edit Links to Files for a workbook with links, which opens the classic Edit Links dialog (Source, Type, Update, Status; Update Values, Change Source…, Open Source, Break Link, Check Status, Startup Prompt…). Break Link asks first; Change Source and Startup Prompt open over Edit Links and return to it. All of it runs the data.* link commands. Opening a workbook with links shows the message bar "Security Warning: Automatic update of links has been disabled" with Enable Content. message_bar.rs is a small reusable mechanism: bars come from the active document's engine state, each with a command button and a close button. German labels follow German Excel (Arbeitsmappenlinks, Verknüpfungen mit Dateien bearbeiten, Werte aktualisieren, Quelle ändern…, Quelle öffnen, Verknüpfung löschen, Status prüfen, Eingabeaufforderung beim Start…, Sicherheitswarnung, Inhalt aktivieren). Generic words carry a context (`Workbook Links|Source`) so they don't collide with other features' translations. The open warning "links to external workbooks were kept; they are not followed or refreshed" is gone: links are now refreshed on request, and the security warning says what Excel says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
file-format-parity (externalLink parts written from the model when a link changes, workbookPr updateLinks), gaps §12 (what works and what's left for links), ROADMAP progress log, ui-parity and target-app-parity rows. An MCP test runs the link commands through execute_command. The command-sequence fuzzer leaves out the link commands that read files or open a document, as it does for file.open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
neilcawse
added a commit
to neilcawse/gridcraft
that referenced
this pull request
Oct 14, 2026
Main now quotes the sheet part of a sheet-qualified name, so after the rebase a name of a linked workbook printed as '[1]'!Rate, in the formula bar and in saved files, where it names a sheet called [1] in this workbook. Excel writes [1]!Rate. Same change as in storytold#1200. Co-authored-by: Herr-Enklo <168219178+Herr-Enklo@users.noreply.github.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on #464 by @neilcawse (formulas into linked workbooks calculate from the values saved with the link) and #829 by @marcoarnulfo (references typed by file name or path go through a link, fixes #804). Their commits are kept, with their authorship. #829's commits were cherry-picked onto current #464; conflict resolutions only adapt to main (
external_booksis anArcnow,WorkbookKeptchanged shape).One reconciling commit lets #829's typed file names through #464's
[n]entry check.[-1],[ 1]and[Book2]are still refused, as #464's review asked. It also fixes two printing issues:[1]!Rateprinted as'[1]'!Rate, and link names were quoted twice.What this adds: Excel's link management
Workbook::source_dir(XLSX: Save As into another folder keeps links on the same workbook #824)workbookPr/@updateLinks(ECMA-376ST_UpdateLinks); the default is not written.message_bar.rs.[n]move updata.workbookLinks,data.editLinks,data.refreshLinks,data.checkLinkStatus,data.changeLinkSource,data.openLinkSource,data.breakLink,data.linkStartupPrompt,data.enableLinkUpdates. The CLI and MCP reach all of them. In the browser, the file-reading commands are disabled with a reason.Expected overlap
The Get & Transform PR from the same fork also builds the Queries & Connections group and its own security bar. Whichever lands second needs a small reconcile; I'll rebase it.
Not included
Tests
crates/engine/tests/workbook_links.rs: update, missing source, missing sheet, change source, break link, startup prompt persistence, Enable Content, no file access, hostile params.cargo xtask ci: all 8 steps pass (1636 tests).🤖 Generated with Claude Code