diff --git a/.eslintignore b/.eslintignore index 1bec93b8c..37928812f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -11,6 +11,7 @@ src/interpreter/plugin/3rdparty *.config.js karma.* doc +test/unit/_setupFiles/*.js # Auto-generated directories commonjs @@ -25,4 +26,3 @@ test-jasmine test-jest typedoc typings -test/_setupFiles/*.js diff --git a/.eslintrc.js b/.eslintrc.js index b89b2641d..9b8544c84 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -90,7 +90,6 @@ module.exports = { 'jsdoc/empty-tags': 'warn', 'jsdoc/implements-on-classes': 'warn', 'jsdoc/multiline-blocks': 'warn', - 'jsdoc/tag-lines': 'warn', 'jsdoc/no-multi-asterisks': 'warn', 'jsdoc/require-param-description': 'warn', 'jsdoc/require-param-name': 'warn', @@ -104,8 +103,9 @@ module.exports = { 'jsdoc/require-yields-check': 'warn', 'jsdoc/valid-types': 'warn', 'jsdoc/require-jsdoc': ['warn', { + checkConstructors: false, require: { - ArrowFunctionExpression: true, + ArrowFunctionExpression: false, ClassDeclaration: true, ClassExpression: true, FunctionDeclaration: true, diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 4ad2abd22..0c008061a 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -18,7 +18,7 @@ jobs: audit: strategy: matrix: - node-version: [ '20' ] + node-version: [ '22' ] os: [ 'ubuntu-latest' ] name: audit runs-on: ${{ matrix.os }} diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index df0fc6216..526211df2 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -18,7 +18,7 @@ jobs: publish-docs: strategy: matrix: - node-version: [ '20' ] + node-version: [ '22' ] os: [ 'ubuntu-latest' ] name: build-docs runs-on: ${{ matrix.os }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57f2b8b20..8a0b584a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [ 20, 22 ] + node-version: [ 20, 22, 24 ] os: [ ubuntu-latest, windows-latest, macos-latest ] install-command: [ i, ci ] runs-on: ${{ matrix.os }} diff --git a/.github/workflows/codeql-advanced.yml b/.github/workflows/codeql-advanced.yml new file mode 100644 index 000000000..ec7ce58ff --- /dev/null +++ b/.github/workflows/codeql-advanced.yml @@ -0,0 +1,100 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: [ "master", "develop", "milestone*" ] + pull_request: + branches: [ "master", "develop", "milestone*" ] + schedule: + - cron: '37 18 * * 6' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # πŸ“š See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 792b2f30d..8d10020c2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,7 +18,7 @@ jobs: lint: strategy: matrix: - node-version: [ '20' ] + node-version: [ '22' ] os: [ 'ubuntu-latest' ] name: lint runs-on: ${{ matrix.os }} diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 64a417635..f70b6b37d 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -14,7 +14,7 @@ jobs: performance-test: strategy: matrix: - node-version: [ '20' ] + node-version: [ '22' ] os: [ 'ubuntu-latest' ] name: Test performance runs-on: ${{ matrix.os }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e884f7ae8..acc67e571 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,6 +1,6 @@ name: Publish permissions: - contents: read + contents: write pages: write on: @@ -12,7 +12,7 @@ jobs: publish-docs: strategy: matrix: - node-version: [ '20' ] + node-version: [ '22' ] os: [ 'ubuntu-latest' ] name: publish-docs runs-on: ${{ matrix.os }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1853ec7c7..51a87c303 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: unit-tests: strategy: matrix: - node-version: [ '20' ] + node-version: [ '22' ] os: [ 'ubuntu-latest' ] name: unit-tests runs-on: ${{ matrix.os }} @@ -37,7 +37,7 @@ jobs: - name: Run tests run: | npm run test:unit.ci -- --coverage - + - name: Upload coverage to Codecov uses: codecov/codecov-action@6004246f47ab62d32be025ce173b241cd84ac58e # https://github.com/codecov/codecov-action/releases/tag/v1.0.13 env: @@ -46,7 +46,7 @@ jobs: browser-tests: strategy: matrix: - node-version: [ '20' ] + node-version: [ '22' ] os: [ 'ubuntu-latest' ] name: browser-tests runs-on: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index b47432ccd..1d5eb450d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +## [3.1.0] - 2025-10-14 + +### Changed + +- Renamed the `arraySizeMethod` parameter in the `FunctionMetadata` interface to `sizeOfResultArrayMethod`. The `arraySizeMethod` is deprecated and will be removed in one of the next major releases. [#1401](https://github.com/handsontable/hyperformula/issues/1401) +- Renamed the `arrayFunction` parameter in the `FunctionMetadata` interface to `enableArrayArithmeticForArguments`. The `arrayFunction` is deprecated and will be removed in one of the next major releases. [#1401](https://github.com/handsontable/hyperformula/issues/1401) + +### Fixed + +- Fixed an issue where the `OFFSET` function was ignoring the sheet reference in the provided address. [#1477](https://github.com/handsontable/hyperformula/issues/1477) + ## [3.0.1] - 2025-08-11 ### Fixed diff --git a/DEV_DOCS.md b/DEV_DOCS.md new file mode 100644 index 000000000..0197a804c --- /dev/null +++ b/DEV_DOCS.md @@ -0,0 +1,9 @@ +# Dev Docs + +Random notes and things to know useful for maintainers and contributors. + +## Sources of the function translations + +HF supports internationalization and provides the localized function names for all built-in languages. When looking for the valid translations for the new functions, try these sources: +- https://support.microsoft.com/en-us/office/excel-functions-translator-f262d0c0-991c-485b-89b6-32cc8d326889 +- http://dolf.trieschnigg.nl/excel/index.php diff --git a/README.md b/README.md index 6fe85f9cc..f82fba5e9 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ hf.setCellContents({ sheet: sheetId, row: 0, col: 0 }, [['Monthly Payment', '=PM console.log(`${hf.getCellValue({ sheet: sheetId, row: 0, col: 0 })}: ${hf.getCellValue({ sheet: sheetId, row: 0, col: 1 })}`); ``` -[Run this code in StackBlitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.0.x/mortgage-calculator) +[Run this code in StackBlitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.1.x/mortgage-calculator) ## Contributing diff --git a/docs/guide/basic-operations.md b/docs/guide/basic-operations.md index 591308df1..0bcc0a771 100644 --- a/docs/guide/basic-operations.md +++ b/docs/guide/basic-operations.md @@ -15,16 +15,16 @@ absolute, in all sheets affected by the change. Operations affecting only the dependency graph should not decrease performance. However, multiple operations that have an impact on -calculation results may affect performance; these are `clearSheet`, -`setSheetContent`, `setCellContents`, `addNamedExpression`, -`changeNamedExpression`, and `removeNamedExpression`. It is advised +calculation results may affect performance; these are [`clearSheet`](../api/classes/hyperformula.md#clearsheet), +[`setSheetContent`](../api/classes/hyperformula.md#setsheetcontent), [`setCellContents`](../api/classes/hyperformula.md#setcellcontents), [`addNamedExpression`](../api/classes/hyperformula.md#addnamedexpression), +[`changeNamedExpression`](../api/classes/hyperformula.md#changenamedexpression), and [`removeNamedExpression`](../api/classes/hyperformula.md#removenamedexpression). It is advised to [batch](batch-operations.md) them. ## Sheets ### Adding a sheet -A sheet can be added by using the `addSheet` method. You can pass a +A sheet can be added by using the [`addSheet`](../api/classes/hyperformula.md#addsheet) method. You can pass a name for it or leave it without a parameter. In the latter case the method will create an autogenerated name for it. That name can then be returned for further use. @@ -37,7 +37,7 @@ const myNewSheet = hfInstance.addSheet(); hfInstance.addSheet('SheetName'); ``` -You can also count sheets by using the `countSheets` method. This +You can also count sheets by using the [`countSheets`](../api/classes/hyperformula.md#countsheets) method. This method does not require any parameters. ```javascript @@ -47,7 +47,7 @@ const sheetsCount = hfInstance.countSheets(); ### Removing a sheet -A sheet can be removed by using the `removeSheet` method. To do that +A sheet can be removed by using the [`removeSheet`](../api/classes/hyperformula.md#removesheet) method. To do that you need to pass a mandatory parameter: the ID of a sheet to be removed. This method returns [an array of changed cells](#changes-array). @@ -59,13 +59,13 @@ const changes = hfInstance.removeSheet(0); ### Renaming a sheet -A sheet can be renamed by using the `renameSheet` method. You need to +A sheet can be renamed by using the [`renameSheet`](../api/classes/hyperformula.md#renamesheet) method. You need to pass the ID of a sheet you want to rename (you can get it with the -`getSheetId` method only if you know its name) along with a new name +[`getSheetId`](../api/classes/hyperformula.md#getsheetid) method only if you know its name) along with a new name as the first and second parameters, respectively. ```javascript -// rename the first sheet +// rename the first sheet hfInstance.renameSheet(0, 'NewSheetName'); // you can retrieve the sheet ID if you know its name @@ -77,7 +77,7 @@ hfInstance.renameSheet(sheetID, 'AnotherNewName'); ### Clearing a sheet -A sheet's content can be cleared with the `clearSheet` method. You need +A sheet's content can be cleared with the [`clearSheet`](../api/classes/hyperformula.md#clearsheet) method. You need to provide the ID of a sheet whose content you want to clear. This method returns [an array of changed cells](#changes-array). @@ -89,7 +89,7 @@ const changes = hfInstance.clearSheet(0); ### Replacing sheet content Instead of removing and adding the content of a sheet you can replace -it right away. To do so use `setSheetContent`, in which you can pass +it right away. To do so use [`setSheetContent`](../api/classes/hyperformula.md#setsheetcontent), in which you can pass the sheet ID and its new values. This method returns [an array of changed cells](#changes-array). @@ -102,7 +102,7 @@ const changes = hfInstance.setSheetContent(0, [['50'], ['60']]); ### Adding rows -You can add one or more rows by using the `addRows` method. The first +You can add one or more rows by using the [`addRows`](../api/classes/hyperformula.md#addrows) method. The first parameter you need to pass is a sheet ID, and the second parameter represents the position and the size of a block of rows to be added. This method returns [an array of changed cells](#changes-array). @@ -115,7 +115,7 @@ const changes = hfInstance.addRows(0, [0, 2]); ### Removing rows -You can remove one or more rows by using the `removeRows` method. The +You can remove one or more rows by using the [`removeRows`](../api/classes/hyperformula.md#removerows) method. The first parameter you need to pass is a sheet ID, and the second parameter represents the position and the size of a block of rows to be removed. @@ -129,13 +129,13 @@ const changes = hfInstance.removeRows(0, [0, 2]); ### Moving rows -You can move one or more rows by using the `moveRows` method. You need +You can move one or more rows by using the [`moveRows`](../api/classes/hyperformula.md#moverows) method. You need to pass the following parameters: * Sheet ID * Starting row * Number of rows to be moved -* Target row +* [Target row](../api/classes/hyperformula.md#moverows) This method returns [an array of changed cells](#changes-array). @@ -147,9 +147,9 @@ const changes = hfInstance.moveRows(0, 0, 1, 2); ### Reordering rows -You can change the order of rows by using the `setRowOrder` method. You need to pass the following parameters: +You can change the order of rows by using the [`setRowOrder`](../api/classes/hyperformula.md#setroworder) method. You need to pass the following parameters: * Sheet ID -* New row order +* [New row order](../api/classes/hyperformula.md#setroworder) This method returns [an array of changed cells](#changes-array). @@ -162,7 +162,7 @@ const changes = hfInstance.setRowOrder(0, [2, 1, 0]); ### Adding columns -You can add one or more columns by using the `addColumns` method. +You can add one or more columns by using the [`addColumns`](../api/classes/hyperformula.md#addcolumns) method. The first parameter you need to pass is a sheet ID, and the second parameter represents the position and the size of a block of columns to be added. @@ -176,7 +176,7 @@ const changes = hfInstance.addColumns(0, [0, 2]); ### Removing columns -You can remove one or more columns by using the `removeColumns` method. +You can remove one or more columns by using the [`removeColumns`](../api/classes/hyperformula.md#removecolumns) method. The first parameter you need to pass is a sheet ID, and the second parameter represents the position and the size of a block of columns to be removed. @@ -190,27 +190,27 @@ const changes = hfInstance.removeColumns(0, [0, 2]); ### Moving columns -You can move one or more columns by using the `moveColumns` method. +You can move one or more columns by using the [`moveColumns`](../api/classes/hyperformula.md#movecolumns) method. You need to pass the following parameters: * Sheet ID * Starting column * Number of columns to be moved -* Target column +* [Target column](../api/classes/hyperformula.md#movecolumns) This method returns [an array of changed cells](#changes-array). ```javascript // track the changes triggered by moving -// the first column in the first sheet into column 2 +// the first column in the first sheet into column 2 const changes = hfInstance.moveColumns(0, 0, 1, 2); ``` ### Reordering columns -You can change the order of columns by using the `setColumnOrder` method. You need to pass the following parameters: +You can change the order of columns by using the [`setColumnOrder`](../api/classes/hyperformula.md#setcolumnorder) method. You need to pass the following parameters: * Sheet ID -* New column order +* [New column order](../api/classes/hyperformula.md#setcolumnorder) This method returns [an array of changed cells](#changes-array). @@ -222,19 +222,19 @@ const changes = hfInstance.setColumnOrder(0, [2, 1, 0]); ## Cells ::: tip -By default, cells are identified using a `SimpleCellAddress` which +By default, cells are identified using a [`SimpleCellAddress`](../api/interfaces/simplecelladdress) which consists of a sheet ID, column ID, and row ID, like this: `{ sheet: 0, col: 0, row: 0 }` Alternatively, you can work with the **A1 notation** known from spreadsheets like Excel or Google Sheets. The API provides the helper -function `simpleCellAddressFromString` which you can use to retrieve -the `SimpleCellAddress` . +function [`simpleCellAddressFromString`](../api/globals.md#simplecelladdressfromstring) which you can use to retrieve +the [`SimpleCellAddress`](../api/interfaces/simplecelladdress) . ::: ### Moving cells -You can move one or more cells using the `moveCells` method. You need +You can move one or more cells using the [`moveCells`](../api/classes/hyperformula.md#movecells) method. You need to pass the following parameters: * Source range ([SimpleCellRange](../api/interfaces/simplecellrange)) @@ -256,8 +256,8 @@ const changes = hfInstance.moveCells({ start: source, end: source }, destination ### Updating cells You can set the content of a block of cells by using the -`setCellContents` method. You need to pass the top left corner address -of a block as a simple cell address, along with the content to be set. +[`setCellContents`](../api/classes/hyperformula.md#setcellcontents) method. You need to pass the top left corner address +of a block as a [`SimpleCellAddress`](../api/interfaces/simplecelladdress), along with the content to be set. It can be content for either a single cell or a set of cells in an array. This method returns [an array of changed cells](#changes-array). @@ -269,8 +269,8 @@ const changes = hfInstance.setCellContents({ col: 3, row: 0, sheet: 0 }, [['=B1' ### Getting cell value -You can get the value of a cell by using `getCellValue` . Remember to -pass the coordinates as a `SimpleCellAddress` . +You can get the value of a cell by using [`getCellValue`](../api/classes/hyperformula.md#getcellvalue) . Remember to +pass the coordinates as a [`SimpleCellAddress`](../api/interfaces/simplecelladdress) . ```javascript // get the value of the B1 cell @@ -279,8 +279,8 @@ const B1Value = hfInstance.getCellValue({ sheet: 0, col: 1, row: 0 }); ### Getting cell formula -You can retrieve the formula from a cell by using `getCellFormula`. -Remember to pass the coordinates as a `SimpleCellAddress` . +You can retrieve the formula from a cell by using [`getCellFormula`](../api/classes/hyperformula.md#getcellformula). +Remember to pass the coordinates as a [`SimpleCellAddress`](../api/interfaces/simplecelladdress) . ```javascript // get the formula from the A1 cell @@ -355,7 +355,7 @@ if (!isRemovable) { ## Changes array -All data modification methods return an array of `ExportedChange`. +All data modification methods return an array of [`ExportedChange`](../api/globals.md#exportedchange). This is a collection of cells whose **values** were affected by an operation, together with their absolute addresses and new values. diff --git a/docs/guide/building.md b/docs/guide/building.md index fd87ba93f..a781b05b8 100644 --- a/docs/guide/building.md +++ b/docs/guide/building.md @@ -38,7 +38,7 @@ format , builds ES6 version * `npm run bundle:languages` - builds the languages * `npm run bundle:typings` - generates TypeScript typing, only emits β€˜.d.ts’ declaration files -We use the Node 20 LTS in the build-chain and recommend this version for building. Note that for using (not building) HyperFormula, a wider range of Node versions is supported. +We use the Node 22 LTS in the build-chain and recommend this version for building. Note that for using (not building) HyperFormula, a wider range of Node versions is supported. ## Verify the build diff --git a/docs/guide/built-in-functions.md b/docs/guide/built-in-functions.md index adb05c579..07d4075c6 100644 --- a/docs/guide/built-in-functions.md +++ b/docs/guide/built-in-functions.md @@ -64,8 +64,8 @@ Total number of functions: **{{ $page.functionsCount }}** | Function ID | Description | Syntax | |:-----------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------| | DATE | Returns the specified date as the number of full days since [`nullDate`](../api/interfaces/configparams.md#nulldate). | DATE(Year, Month, Day) | -| DATEDIF | Calculates distance between two dates, in provided unit parameter. | DATEDIF(Date1, Date2, Units) | -| DATEVALUE | Parses a date string and returns it as the number of full days since [`nullDate`](../api/interfaces/configparams.md#nulldate).

Accepts formats set by the [`dateFormats`](../api/interfaces/configparams.md#dateformats) option. | DATEVALUE(Datestring) | +| DATEDIF | Calculates distance between two dates.
Supported units: "D" (days), "M" (months), "Y" (years), "MD" (days ignoring months and years), "YM" (months ignoring years), or "YD" (days ignoring years). | DATEDIF(Date1, Date2, Unit) | +| DATEVALUE | Parses a date string and returns it as the number of full days since [`nullDate`](../api/interfaces/configparams.md#nulldate).
Accepts formats set by the [`dateFormats`](../api/interfaces/configparams.md#dateformats) option. | DATEVALUE(Datestring) | | DAY | Returns the day of the given date value. | DAY(Number) | | DAYS | Calculates the difference between two date values. | DAYS(Date2, Date1) | | DAYS360 | Calculates the difference between two date values in days, in 360-day basis. | DAYS360(Date2, Date1[, Format]) | @@ -81,7 +81,7 @@ Total number of functions: **{{ $page.functionsCount }}** | NOW | Returns current date + time as a number of days since [`nullDate`](../api/interfaces/configparams.md#nulldate). | NOW() | | SECOND | Returns second component of given time. | SECOND(Time) | | TIME | Returns the number that represents a given time as a fraction of full day. | TIME(Hour, Minute, Second) | -| TIMEVALUE | Parses a time string and returns a number that represents it as a fraction of a full day.

Accepts formats set by the [`timeFormats`](../api/interfaces/configparams.md#timeformats) option. | TIMEVALUE(Timestring) | +| TIMEVALUE | Parses a time string and returns a number that represents it as a fraction of a full day.
Accepts formats set by the [`timeFormats`](../api/interfaces/configparams.md#timeformats) option. | TIMEVALUE(Timestring) | | TODAY | Returns an integer representing the current date as the number of full days since [`nullDate`](../api/interfaces/configparams.md#nulldate). | TODAY() | | WEEKDAY | Computes a number between 1-7 representing the day of week. | WEEKDAY(Date, Type) | | WEEKNUM | Returns a week number that corresponds to the week of year. | WEEKNUM(Date, Type) | @@ -499,7 +499,7 @@ Total number of functions: **{{ $page.functionsCount }}** | SPLIT | Divides the provided text using the space character as a separator and returns the substring at the zero-based position specified by the second argument.
`SPLIT("Lorem ipsum", 0) -> "Lorem"`
`SPLIT("Lorem ipsum", 1) -> "ipsum"` | SPLIT(Text, Index) | | SUBSTITUTE | Returns string where occurrences of Old_text are replaced by New_text. Replaces only specific occurrence if last parameter is provided. | SUBSTITUTE(Text, Old_text, New_text, [Occurrence]) | | T | Returns text if given value is text, empty string otherwise. | T(Value) | -| TEXT | Converts a number into text according to a given format.

By default, accepts the same formats that can be passed to the [`dateFormats`](../api/interfaces/configparams.md#dateformats) option, but can be further customized with the [`stringifyDateTime`](../api/interfaces/configparams.md#stringifydatetime) option. | TEXT(Number, Format) | +| TEXT | Converts a number into text according to a given format.
By default, accepts the same formats that can be passed to the [`dateFormats`](../api/interfaces/configparams.md#dateformats) option, but can be further customized with the [`stringifyDateTime`](../api/interfaces/configparams.md#stringifydatetime) option. | TEXT(Number, Format) | | TRIM | Strips extra spaces from text. | TRIM("Text") | | UNICHAR | Returns the character created by using provided code point. | UNICHAR(Number) | | UNICODE | Returns the Unicode code point of a first character of a text. | UNICODE(Text) | diff --git a/docs/guide/compatibility-with-google-sheets.md b/docs/guide/compatibility-with-google-sheets.md index 1d2497063..5e98ea3b4 100644 --- a/docs/guide/compatibility-with-google-sheets.md +++ b/docs/guide/compatibility-with-google-sheets.md @@ -15,6 +15,17 @@ Still, with the right configuration, you can achieve nearly full compatibility. ## Configure compatibility with Google Sheets +### `TRUE` and `FALSE` constants + +Google Sheets has built-in constants (keywords) for the boolean values (`TRUE` and `FALSE`). + +To set up HyperFormula in the same way, define `TRUE` and `FALSE` as [named expressions](named-expressions.md), by using HyperFormula's [`TRUE()`](built-in-functions.md#logical) and [`FALSE()`](built-in-functions.md#logical) functions. + +```js +hfInstance.addNamedExpression('TRUE', '=TRUE()'); +hfInstance.addNamedExpression('FALSE', '=FALSE()'); +``` + ### Array arithmetic mode In Google Sheets, the [array arithmetic mode](arrays.md#array-arithmetic-mode) is disabled by default. @@ -97,4 +108,11 @@ const options = { leapYear1900: false, // set by default smartRounding: true, // set by default }; + +// call the static method to build a new instance +const hfInstance = HyperFormula.buildEmpty(options); + +// define TRUE and FALSE constants +hfInstance.addNamedExpression('TRUE', '=TRUE()'); +hfInstance.addNamedExpression('FALSE', '=FALSE()'); ``` diff --git a/docs/guide/compatibility-with-microsoft-excel.md b/docs/guide/compatibility-with-microsoft-excel.md index 65f252f4e..c26d9efe5 100644 --- a/docs/guide/compatibility-with-microsoft-excel.md +++ b/docs/guide/compatibility-with-microsoft-excel.md @@ -56,7 +56,7 @@ Related options: Microsoft Excel has built-in constants (keywords) for the boolean values (`TRUE` and `FALSE`). -To set up HyperFormula in the same way, define `TRUE` and `FALSE` as [named expressions](named-expressions.md), by using HyperFormula's [`TRUE`](built-in-functions.md#logical) and [`FALSE`](built-in-functions.md#logical) functions. +To set up HyperFormula in the same way, define `TRUE` and `FALSE` as [named expressions](named-expressions.md), by using HyperFormula's [`TRUE()`](built-in-functions.md#logical) and [`FALSE()`](built-in-functions.md#logical) functions. ```js hfInstance.addNamedExpression('TRUE', '=TRUE()'); diff --git a/docs/guide/custom-functions.md b/docs/guide/custom-functions.md index 3444cdacd..c19f3494e 100644 --- a/docs/guide/custom-functions.md +++ b/docs/guide/custom-functions.md @@ -258,12 +258,12 @@ export class MyCustomPlugin extends FunctionPlugin { A function that returns an array will cause the `VALUE!` error unless you also declare a companion method for the array size. To do that, provide the -`arraySizeMethod` that calculates the size of the result array based on the +`sizeOfResultArrayMethod` that calculates the size of the result array based on the function arguments and returns an instance of the [`ArraySize` class](../api/classes/arraysize.md). ::: tip -When you use your custom function in a formula, `arraySizeMethod` is triggered every time the formula changes, but not when the dependencies of the formula change. +When you use your custom function in a formula, `sizeOfResultArrayMethod` is triggered every time the formula changes, but not when the dependencies of the formula change. This can cause unexpected behavior if the size of the result array depends on the values in the referenced cells. ::: @@ -286,7 +286,7 @@ export class MyCustomPlugin extends FunctionPlugin { MyCustomPlugin.implementedFunctions = { DOUBLE_RANGE: { method: 'doubleRange', - arraySizeMethod: 'doubleRangeResultArraySize', + sizeOfResultArrayMethod: 'doubleRangeResultArraySize', parameters: [{ argumentType: FunctionArgumentType.RANGE }], }, }; @@ -363,7 +363,7 @@ This demo contains the implementation of both the [`DOUBLE_RANGE`](#advanced-custom-function-example) custom functions.