From 72fa392d8b3d122b7972fa8732e794215cd183a1 Mon Sep 17 00:00:00 2001 From: marcin-kordas-hoc Date: Tue, 28 Apr 2026 02:33:43 +0000 Subject: [PATCH 1/5] Docs: HF-161 add OFFSET function limitations to known-limitations guide --- docs/guide/known-limitations.md | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/guide/known-limitations.md b/docs/guide/known-limitations.md index 72753b9b2..a673b3036 100644 --- a/docs/guide/known-limitations.md +++ b/docs/guide/known-limitations.md @@ -38,3 +38,39 @@ you can't compare the arguments in a formula like this: * The INDEX function doesn't support returning whole rows or columns of the source range – it always returns the contents of a single cell. * The FILTER function accepts either single rows of equal width or single columns of equal height. In other words, all arrays passed to the FILTER function must have equal dimensions, and at least one of those dimensions must be 1. * Array-producing functions (e.g., SEQUENCE, FILTER) require their output dimensions to be determinable at parse time. Passing cell references or formulas as dimension arguments (e.g., `=SEQUENCE(A1)`) results in a `#VALUE!` error, because the output size cannot be resolved before evaluation. + +### OFFSET function + +Unlike Excel and Google Sheets, HyperFormula resolves the OFFSET function at parse time rather than during evaluation. The parser inspects the arguments and rewrites the expression into a plain cell reference or range. This keeps the dependency graph accurate but imposes several restrictions. + +* The first argument must be a reference to a single cell. Passing a range raises a parsing error. + + ```js + // Parsing error: First argument to OFFSET is not a reference + hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1:B1, 0, 0)'); + ``` + +* The row-shift, column-shift, height, and width arguments must be static integer literals known at parse time. Cell references and formulas passed as shift or size arguments produce a parsing error. + + ```js + // Parsing error: Second argument to OFFSET is not a static number + hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1, C3, 0)'); + ``` + + Lifting this restriction requires treating OFFSET as a regular interpreted function. The work is tracked in [issue #910](https://github.com/handsontable/hyperformula/issues/910). + +* The height and width arguments must be positive integers. Values less than 1 and non-integer values are rejected at parse time. + +* When the computed target falls outside the sheet, OFFSET evaluates to a `#REF!` error indicating the resulting reference is out of the sheet bounds. + + ```js + // Cell A1 evaluates to #REF! + hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1, -1, 0)'); + ``` + +* Because OFFSET is resolved at parse time, `getCellFormula` returns the computed reference, not the original `OFFSET` call. + + ```js + const hf = HyperFormula.buildFromArray([[1, 45, '=OFFSET(A1, 0, 1)']]); + hf.getCellFormula({ sheet: 0, row: 0, col: 2 }); // '=B1' + ``` From d960d42debc431e73c81611d4595929f81ec1ef3 Mon Sep 17 00:00:00 2001 From: marcin-kordas-hoc Date: Tue, 28 Apr 2026 02:34:36 +0000 Subject: [PATCH 2/5] Docs: HF-161 remove OFFSET row from list-of-differences (consolidated to known-limitations) --- docs/guide/list-of-differences.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/guide/list-of-differences.md b/docs/guide/list-of-differences.md index 9dac88022..32246f80b 100644 --- a/docs/guide/list-of-differences.md +++ b/docs/guide/list-of-differences.md @@ -35,7 +35,6 @@ See a full list of differences between HyperFormula, Microsoft Excel, and Google | TIMEVALUE function | =TIMEVALUE("14:31") | Type of the returned value: `CellValueDetailedType.NUMBER_TIME` (compliant with the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html) standard) | Cell auto-formatted as **regular number** | Cell auto-formatted as **regular number** | | EDATE function | =EDATE(DATE(2019, 7, 31), 1) | Type of the returned value: `CellValueDetailedType.NUMBER_DATE`. This is non-compliant with the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html) standard, which defines the return type as a Number, while describing it as a Date serial number through the function summary. | Cell auto-formatted as **date** | Cell auto-formatted as **regular number** | | EOMONTH function | =EOMONTH(DATE(2019, 7, 31), 1) | Type of the returned value: `CellValueDetailedType.NUMBER_DATE`. This is non-compliant with the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html) standard, which defines the return type as a Number, while describing it as a Date serial number through the function summary. | Cell auto-formatted as **date** | Cell auto-formatted as **regular number** | -| OFFSET function | =OFFSET(A1:B1, 0, 0) | First parameter must be a **reference to a single cell**. | First parameter may be a single cell or a range. | First parameter may be a single cell or a range. | ## Built-in functions From abb84e5c44902705042bcc8c4a368b71d9fcf2bc Mon Sep 17 00:00:00 2001 From: marcin-kordas-hoc Date: Wed, 29 Apr 2026 10:14:05 +0000 Subject: [PATCH 3/5] Docs: HF-161 paraphrase OFFSET parser error code comments Per Q2 principle (describe runtime-observable behavior, not internal strings): replace verbatim copies of internal parser error messages with behavioral descriptions. Future internal-string refactors will no longer silently invalidate these doc comments. --- docs/guide/known-limitations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/known-limitations.md b/docs/guide/known-limitations.md index a673b3036..fd6ec7c60 100644 --- a/docs/guide/known-limitations.md +++ b/docs/guide/known-limitations.md @@ -46,14 +46,14 @@ Unlike Excel and Google Sheets, HyperFormula resolves the OFFSET function at par * The first argument must be a reference to a single cell. Passing a range raises a parsing error. ```js - // Parsing error: First argument to OFFSET is not a reference + // Raises a parsing error — the first argument must be a single cell, not a range hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1:B1, 0, 0)'); ``` * The row-shift, column-shift, height, and width arguments must be static integer literals known at parse time. Cell references and formulas passed as shift or size arguments produce a parsing error. ```js - // Parsing error: Second argument to OFFSET is not a static number + // Raises a parsing error — the row-shift argument must be a static integer literal hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1, C3, 0)'); ``` From 4b5366c5d30bb81560ac3551dadcaa188af421db Mon Sep 17 00:00:00 2001 From: marcin-kordas-hoc Date: Wed, 13 May 2026 11:16:13 +0000 Subject: [PATCH 4/5] Docs: HF-161 drop 'Unlike Excel' framing per known-limitations convention --- docs/guide/known-limitations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/known-limitations.md b/docs/guide/known-limitations.md index fd6ec7c60..5f63d5d16 100644 --- a/docs/guide/known-limitations.md +++ b/docs/guide/known-limitations.md @@ -41,7 +41,7 @@ you can't compare the arguments in a formula like this: ### OFFSET function -Unlike Excel and Google Sheets, HyperFormula resolves the OFFSET function at parse time rather than during evaluation. The parser inspects the arguments and rewrites the expression into a plain cell reference or range. This keeps the dependency graph accurate but imposes several restrictions. +HyperFormula resolves the OFFSET function at parse time rather than during evaluation. The parser inspects the arguments and rewrites the expression into a plain cell reference or range. This keeps the dependency graph accurate but imposes several restrictions. * The first argument must be a reference to a single cell. Passing a range raises a parsing error. @@ -68,7 +68,7 @@ Unlike Excel and Google Sheets, HyperFormula resolves the OFFSET function at par hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1, -1, 0)'); ``` -* Because OFFSET is resolved at parse time, `getCellFormula` returns the computed reference, not the original `OFFSET` call. +* OFFSET is resolved at parse time, so `getCellFormula` returns the computed reference, not the original `OFFSET` call. ```js const hf = HyperFormula.buildFromArray([[1, 45, '=OFFSET(A1, 0, 1)']]); From 8fb75e9d0749f3bd558bd8bc43d858754bdb617b Mon Sep 17 00:00:00 2001 From: marcin-kordas-hoc Date: Thu, 14 May 2026 05:06:30 +0000 Subject: [PATCH 5/5] Docs: HF-161 clarify parser-error wording per Codex review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace 'Raises a parsing error' wording with explicit 'cell stores a parser error' — the JS API does not throw an exception - Specify 'bare positive integer literals' instead of 'positive integers' to reflect that the parser accepts only NUMBER AST nodes (so `+1` and parenthesised expressions are also rejected, not just non-integers) - Reframe the out-of-sheet bullet to make the parse-time-vs-evaluation distinction explicit (matches Excel value but not detection timing) --- docs/guide/known-limitations.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/guide/known-limitations.md b/docs/guide/known-limitations.md index 5f63d5d16..78409f47d 100644 --- a/docs/guide/known-limitations.md +++ b/docs/guide/known-limitations.md @@ -43,28 +43,28 @@ you can't compare the arguments in a formula like this: HyperFormula resolves the OFFSET function at parse time rather than during evaluation. The parser inspects the arguments and rewrites the expression into a plain cell reference or range. This keeps the dependency graph accurate but imposes several restrictions. -* The first argument must be a reference to a single cell. Passing a range raises a parsing error. +* The first argument must be a reference to a single cell. Passing a range causes the cell to store a parser error (the API call itself does not throw — read the error via `getCellValue`). ```js - // Raises a parsing error — the first argument must be a single cell, not a range + // Cell A1 stores a parser error — the first argument must be a single cell, not a range hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1:B1, 0, 0)'); ``` -* The row-shift, column-shift, height, and width arguments must be static integer literals known at parse time. Cell references and formulas passed as shift or size arguments produce a parsing error. +* The row-shift, column-shift, height, and width arguments must be static integer literals known at parse time. Cell references and formulas passed as shift or size arguments cause the cell to store a parser error. ```js - // Raises a parsing error — the row-shift argument must be a static integer literal + // Cell A1 stores a parser error — the row-shift argument must be a static integer literal hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1, C3, 0)'); ``` Lifting this restriction requires treating OFFSET as a regular interpreted function. The work is tracked in [issue #910](https://github.com/handsontable/hyperformula/issues/910). -* The height and width arguments must be positive integers. Values less than 1 and non-integer values are rejected at parse time. +* The height and width arguments must be bare positive integer literals (the parser accepts only `NUMBER` AST nodes). Unary `+` prefixes, parenthesised expressions, values less than 1, and non-integer values are rejected at parse time. -* When the computed target falls outside the sheet, OFFSET evaluates to a `#REF!` error indicating the resulting reference is out of the sheet bounds. +* When the computed target falls outside the sheet, the parser stores a `#REF!` error in the cell at parse time (rather than during evaluation) with the message *Resulting reference is out of the sheet*. ```js - // Cell A1 evaluates to #REF! + // Cell A1 stores #REF! hf.setCellContents({ sheet: 0, row: 0, col: 0 }, '=OFFSET(A1, -1, 0)'); ```