Skip to content

Add INDIRECT function (HF-27) - #1843

Draft
Tobiadefami wants to merge 3 commits into
developfrom
feature/hf-27-phase2
Draft

Tobiadefami wants to merge 3 commits into
developfrom
feature/hf-27-phase2

Conversation

@Tobiadefami

@Tobiadefami Tobiadefami commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Context

The PR adds the INDIRECT function, without making it volatile.

  • Why: INDIRECT reads an address known only at evaluation time. The parser cannot add that dependency to the graph.
  • What changed:
    • IndirectPlugin.ts: resolves A1 and R1C1 text, cells, ranges and named expressions, on any sheet.
    • DependencyGraph.ts, FormulaVertex.ts, Graph.ts: store each cell or range that INDIRECT read as a runtime dependency of the formula.
    • TopSort.ts, Evaluator.ts, EvaluationPass.ts, EvaluationDeferred.ts: if the target is not computed yet, the formula defers. The sort computes the target first, then retries the formula.
    • SimpleRangeValue.ts: an INDIRECT range records its dependency on first use of its values or address. ROWS and COLUMNS read only its size.
    • Operations.ts, GraphBuilder.ts: sheet, name and structure changes mark INDIRECT formulas dirty.
  • Result: =INDIRECT("B"&A1) recalculates when A1 or the target changes, and not on unrelated edits.

How did you test your changes?

Paired branch in hyperformula-tests: feature/hf-27-phase2 (handsontable/hyperformula-tests#104).

  • npx jest on function-indirect.spec.ts, indirect-dependency-graph.spec.ts and graph.spec.ts: 196 passed.
  • Full Jest suite: 6,875 passed, 17 failed. The 17 are the translation checks: INDIRECT has no name yet in languages other than enGB.
  • npm run lint: no errors.

Compatibility with Excel and Google Sheets

Not verified yet. Results from Excel Online (en-US) will be added before review.

Formula Excel Google Sheets HyperFormula

Public API changes

None, apart from the new INDIRECT function.

Out of scope and follow-ups

  • Whole-column and whole-row text ("B:B", "1:1") and spill references ("D1#").
  • OFFSET with computed arguments: a separate task, on the same mechanism.

Still to do before review: translations, docs, changelog entry.

Types of changes

  • Breaking change (existing functionality no longer works as before) – agreed with the maintainers
  • New feature or improvement (a non-breaking change that adds functionality)
  • Bug fix (a non-breaking change that fixes an issue)
  • Additional language file, or a change to an existing language file (translations)
  • Change to the documentation

Related issues

  1. Addresses Add support for INDIRECT #1260 (task HF-27). Whole-column and whole-row text is still missing, see above.

Checklist

🤖 Generated with Claude Code

Tobiadefami and others added 3 commits October 24, 2026 15:40
INDIRECT resolves its text at evaluation time and records the cell it reads as a
runtime dependency in the graph, so it is not volatile. When the target is not
current yet in the running pass, the evaluation is deferred: the sort computes the
target first, with an explicit stack, and then retries the formula.

Covers A1 references to a single cell, on the same or another sheet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
INDIRECT now accepts an A1 range, a named expression and R1C1 text (absolute,
relative, ranges, sheet-qualified). A range is read lazily: its cells become a
runtime dependency of the formula, through the range vertex, the first time the
range's values or address are used, so ROWS and COLUMNS read only its size.
Changes to named expressions mark INDIRECT formulas for recalculation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…evaluation

- Moving a cell that an INDIRECT formula read marks that formula dirty: the
  address in its text does not move with the cell, so it reads the address again.
- A formula whose result is an INDIRECT range records the range as its dependency
  while it is evaluated, like a literal range; a cell that later reads the stored
  range no longer reads cells that are not computed yet.
- Range and empty cell vertices that lose their last runtime dependent are removed
  after the evaluation, not during it, while the sort may still hold them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
hyperformula-docs 5368efa Commit Preview URL

Branch Preview URL
Oct 25 2026, 12:34 AM

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Performance comparison of head (5368efa) vs base (d143456)

                                     testName |   base |   head |  change
-------------------------------------------------------------------------
                                      Sheet A |  297.3 | 309.59 |  +4.13%
                                      Sheet B |  98.67 | 106.63 |  +8.07%
                                      Sheet T |  82.33 |  91.21 | +10.79%
                                Column ranges | 312.37 | 334.09 |  +6.95%
                                Sorted lookup | 9534.9 | 9654.5 |  +1.25%
Sheet A:  change value, add/remove row/column |  10.54 |  10.77 |  +2.18%
 Sheet B: change value, add/remove row/column |  86.29 |  93.89 |  +8.81%
                   Column ranges - add column |  97.43 |   96.4 |  -1.06%
                Column ranges - without batch | 306.35 | 334.89 |  +9.32%
                        Column ranges - batch |  81.74 |  86.18 |  +5.43%

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant