Skip to content

Add TRIMRANGE function (HF-391) - #1842

Draft
Tobiadefami wants to merge 42 commits into
developfrom
feature/HF-391
Draft

Tobiadefami wants to merge 42 commits into
developfrom
feature/HF-391

Conversation

@Tobiadefami

Copy link
Copy Markdown
Collaborator

Context

This PR adds the TRIMRANGE dynamic-array function (HF-391). TRIMRANGE(range, [trim_rows], [trim_cols]) returns a range without the blank rows and columns at its edges.

Important

Stacked on #1796 (DROP), which is stacked on #1722 (TAKE). Until both merge, this diff also shows their commits. This change is the last commit, feat: add TRIMRANGE function (HF-391), plus a changelog link commit. Once #1722 and #1796 merge, this branch will be rebased onto develop.

Behavior, checked against Microsoft Excel Online (en-US):

  • Each trim code is 0 (none), 1 (leading), 2 (trailing) or 3 (both, the default). Fractions, other numbers, text and "" return #VALUE!; numeric text and TRUE/FALSE are accepted.
  • In a range, only an empty cell is blank. Formulas, empty text, 0, FALSE, errors and spaces are content, and blank cells inside the result stay blank.
  • A source with nothing left to keep returns #REF!.

Differences from Excel, listed in list-of-differences.md:

Case HyperFormula Excel
Result size The untrimmed range is reserved; the result fills its top-left corner, the rest stays blank Spills only the trimmed result and follows the data
Whole column or row Spills from the first row or column only, with the sheet's current size Spills from any row
Array or range as a trim code One #VALUE! An array of #VALUE!
Result type Values A reference (ISREF is TRUE)
A1:.C10 trim references Parse error Supported

Implementation

  • TRIMRANGE lives in ArrayPlugin, after TAKE. Codes are read as single values and coerced in the method, so errors are reported in Excel's order.
  • The edges are found by scanning inward, so the cost is the blank border, not the whole range.
  • The whole-column rule is now one helper shared with TAKE. TAKE's results are unchanged.
  • Included: the catalogue entry, the license table entry, the name in every language pack, the changelog and list-of-differences.md rows. Localized names come from Excel Online in each locale; Indonesian keeps the English name.

How did you test your changes?

  • Tests PR: handsontable/hyperformula-tests#103, 142 tests from 143 cases measured in Microsoft Excel Online (en-US), plus scenario tests.
  • Full Jest suite: 523/523 suites, 7,057 tests passed, 3 skipped. TAKE gave identical results on 540 probes before and after the shared helper.
  • Ten deliberate breaks of the code each failed tests, for example 37 when leading columns were not trimmed.
  • npm run compile, npm run docs:generate-function-docs and git diff --check pass. Lint shows no warnings on new lines.

Types of changes

  • Breaking change (a fix or a feature because of which an existing functionality doesn't work as expected anymore)
  • 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. Depends on Add DROP function (HF-384) #1796 (DROP) and Feature/take function #1722 (TAKE).
  2. Tests: handsontable/hyperformula-tests#103

Checklist:

  • I have reviewed the guidelines about Contributing to HyperFormula and I confirm that my code follows the code style of this project.
  • I have signed the Contributor License Agreement.
  • My change is compliant with the OpenDocument standard.
  • My change is compatible with Microsoft Excel, subject to the documented differences.
  • My change is compatible with Google Sheets.
  • I described my changes in the CHANGELOG.md file.
  • My changes require a documentation update.
  • My changes require a migration guide.

🤖 Generated with Claude Code

Tobiadefami and others added 30 commits August 13, 2026 11:28
TAKE shipped with the English name in 10 of 16 packs while 6 carried a
translation, and VSTACK/HSTACK were English in all 16. Microsoft localizes
all three in most locales, so a user could not type the name their Excel
uses.

Names taken from Microsoft's localized "Excel functions (alphabetical)"
page, one locale at a time. Each row there links to the function's own page
using the English slug in the href while the link text is the localized
name, so the lookup is exact:

    <a href="functions/take-function">WYCINEK</a>

Left as English where Microsoft itself does not translate: TAKE, VSTACK and
HSTACK in Indonesian, and VSTACK/HSTACK in Swedish.

Note that a function's own localized page is not a usable source: for
several locales its syntax block still shows the English name even though
the prose and argument names are translated (the French page shows
"=TAKE(tableau, lignes,[colonnes])" while the product uses PRENDRE).

DEV_DOCS records the lookup method and adds the governing policy: ship a
localized name only when it can be confirmed against the product, and keep
the English name otherwise, since an invented name matches nothing, reads
plausibly enough to be typed first, and fails as #NAME?.

No changelog entry: TAKE, VSTACK and HSTACK are all still in [Unreleased],
so no wrong name has been released.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tobiadefami and others added 12 commits September 3, 2026 22:22
Add the DROP dynamic-array function to ArrayPlugin. DROP removes rows and
columns from the start (positive counts) or end (negative counts) of an
array. Counts truncate toward zero, and a zero, omitted, or empty count
drops nothing. Dropping every row or column returns #N/A, because
HyperFormula has no #CALC! error type.

Spill-size prediction uses statically known counts, so dropped rows and
columns are never reserved. A whole-column or whole-row source spills
from its effective size and fits only when the formula starts within the
number of rows or columns dropped, matching Excel.

TAKE and DROP now share the static count parser, source-range lookup,
effective source sizing, and the slice that reads only the kept cells.

Localized names are confirmed in Excel Online for every language pack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A whole-column or whole-row DROP result fits only when the formula
starts within the number of rows or columns dropped. Size prediction
applied that rule only to statically known counts, so a count from a
cell reserved the source's current height wherever the formula was.
On another sheet that spilled where Excel returns #SPILL!; on the
source's own sheet the reservation made the column taller and the
result threw "Resizing to smaller array".

An unresolved count already counts as dropping nothing for the size
bound; it now does for the placement rule too, so the result fits only
in the first row or column. Documented in list-of-differences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add two general rows that apply to array functions whose size is
predicted before evaluation: an error result fills the whole reserved
area, and a size that depends on cell values reserves the upper bound,
so an occupied cell inside it gives #SPILL! where Excel spills. Add a
DROP row for ISREF, which is FALSE because DROP returns values rather
than a reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in develop through the TAKE branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TRIMRANGE removes the blank rows and columns at the edges of a range or
array. A cell of a range is blank only when it is empty, so a formula is
kept even when its value is blank. Each trim code is an integer from 0
to 3; any other value is a #VALUE! error. A source with nothing left to
keep returns #REF!.

The result size is predicted before evaluation, so the untrimmed source
is reserved and the result fills its top-left corner. Whole columns and
rows follow TAKE's sheet-edge rule, now one helper shared by both
functions; TAKE's results are unchanged.

Adds the catalogue entry, the license table entry, the name in every
language pack, list-of-differences rows and a changelog entry.

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

cloudflare-workers-and-pages Bot commented Oct 24, 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 c9973b8 Commit Preview URL

Branch Preview URL
Oct 24 2026, 10:43 PM

@codecov

codecov Bot commented Oct 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.66777% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.35%. Comparing base (79899ee) to head (c9973b8).
⚠️ Report is 2 commits behind head on develop.

Files with missing lines Patch % Lines
hyperformula/src/interpreter/plugin/ArrayPlugin.ts 99.66% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #1842      +/-   ##
===========================================
+ Coverage    97.28%   97.35%   +0.07%     
===========================================
  Files          207      207              
  Lines        16218    16517     +299     
  Branches      3556     3708     +152     
===========================================
+ Hits         15777    16080     +303     
+ Misses         433      429       -4     
  Partials         8        8              
Files with missing lines Coverage Δ
hyperformula/src/error-message.ts 100.00% <100.00%> (ø)
hyperformula/src/i18n/languages/csCZ.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/daDK.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/deDE.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/enGB.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/esES.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/fiFI.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/frFR.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/huHU.ts 100.00% <ø> (ø)
hyperformula/src/i18n/languages/idID.ts 100.00% <ø> (ø)
... and 12 more

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Performance comparison of head (c9973b8) vs base (d143456)

                                     testName |    base |    head | change
--------------------------------------------------------------------------
                                      Sheet A |  443.08 |  475.17 | +7.24%
                                      Sheet B |   141.2 |  147.74 | +4.63%
                                      Sheet T |     125 |  129.73 | +3.78%
                                Column ranges |  581.06 |  583.94 | +0.50%
                                Sorted lookup | 17692.2 | 18157.4 | +2.63%
Sheet A:  change value, add/remove row/column |   12.65 |   12.93 | +2.21%
 Sheet B: change value, add/remove row/column |   121.2 |  126.94 | +4.74%
                   Column ranges - add column |  160.55 |  159.58 | -0.60%
                Column ranges - without batch |   501.4 |  482.23 | -3.82%
                        Column ranges - batch |  123.74 |  120.85 | -2.34%

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.

2 participants