Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8d5373a
Docs: add basic usage snippets to framework integration guides
marcin-kordas-hoc Apr 9, 2026
f919dd3
Implement DCOUNT database function
marcin-kordas-hoc Apr 10, 2026
424f13f
ci: retrigger
marcin-kordas-hoc Apr 10, 2026
086aa08
ci: retrigger after tests PR created
marcin-kordas-hoc Apr 10, 2026
26434dc
Implement DSUM, DCOUNTA, DPRODUCT database functions
marcin-kordas-hoc Apr 10, 2026
22c3433
fixup! Implement DAVERAGE, DMAX, DMIN, DGET database functions
marcin-kordas-hoc Apr 10, 2026
7efebc8
Implement DSTDEV, DSTDEVP, DVAR, DVARP database functions
marcin-kordas-hoc Apr 10, 2026
2d7025e
Implement all 12 database functions (D-functions family)
marcin-kordas-hoc Apr 10, 2026
948132a
fix: remove unnecessary type assertions in DatabasePlugin (lint)
marcin-kordas-hoc Apr 10, 2026
18906bc
Docs: add Database section to built-in-functions.md and nuances to kn…
marcin-kordas-hoc Apr 15, 2026
0dc18ad
refactor: extract shared boilerplate in DatabasePlugin (DRY)
marcin-kordas-hoc Apr 16, 2026
6a14594
fix: remove Excel mention from known-limitations, trailing space
marcin-kordas-hoc Apr 16, 2026
f7d91fc
ci: retrigger after tests repo rebase
marcin-kordas-hoc Apr 16, 2026
594c9a2
fix: Czech DCOUNT translation and boolean field coercion
marcin-kordas-hoc Apr 17, 2026
11b0488
fix: guard resolveFieldIndex against non-finite indices
marcin-kordas-hoc Apr 17, 2026
3b238de
fix: propagate CellError from field and criteria arguments
marcin-kordas-hoc Apr 17, 2026
0099900
fix: Dutch DCOUNTA translation typo (DBAAANTALC -> DBAANTALC)
marcin-kordas-hoc Apr 17, 2026
11cf389
fix: Norwegian DCOUNT translation (ANTALLDB -> DANTALL)
marcin-kordas-hoc Apr 17, 2026
947a9fd
fix: propagate CellError from field cells in D-function aggregations
marcin-kordas-hoc Apr 17, 2026
2727f8e
fix: propagate CellError from field cells in DCOUNT and DCOUNTA too
marcin-kordas-hoc Apr 17, 2026
4e73545
fix: Polish diacritics + DGET CellError explicit guard
marcin-kordas-hoc Apr 17, 2026
42d5e09
fix: correct D-function translations for cs, tr, da, pt per Microsoft…
marcin-kordas-hoc Apr 17, 2026
9d07107
fix: DGET multiple-match check takes priority over field CellError
marcin-kordas-hoc Apr 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Added

- Added 12 database functions: DCOUNT, DSUM, DAVERAGE, DMAX, DMIN, DGET, DPRODUCT, DCOUNTA, DSTDEV, DSTDEVP, DVAR, DVARP. [#1652](https://github.com/handsontable/hyperformula/pull/1652)
- Added new functions: PERCENTILE, PERCENTILE.INC, PERCENTILE.EXC, QUARTILE, QUARTILE.INC, QUARTILE.EXC. [#1650](https://github.com/handsontable/hyperformula/pull/1650)
- Added `maxPendingLazyTransformations` configuration option to control memory usage by limiting accumulated transformations before cleanup. [#1629](https://github.com/handsontable/hyperformula/issues/1629)
- Added a new function: TEXTJOIN. [#1640](https://github.com/handsontable/hyperformula/pull/1640)
Expand Down
21 changes: 19 additions & 2 deletions docs/guide/built-in-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The latest version of HyperFormula has an extensive collection of
**{{ $page.functionsCount }}** functions grouped into categories:

- [Array manipulation](#array-manipulation)
- [Database](#database)
- [Date and time](#date-and-time)
- [Engineering](#engineering)
- [Information](#information)
Expand All @@ -40,8 +41,7 @@ The latest version of HyperFormula has an extensive collection of
- [Statistical](#statistical)
- [Text](#text)

_Some categories such as compatibility, cube, and database are yet to be
supported._
_Some categories such as compatibility and cube are yet to be supported._

::: tip
You can modify the built-in functions or create your own, by adding a [custom function](custom-functions).
Expand Down Expand Up @@ -91,6 +91,23 @@ Total number of functions: **{{ $page.functionsCount }}**
| YEAR | Returns the year as a number according to the internal calculation rules. | YEAR(Number) |
| YEARFRAC | Computes the difference between two date values, in fraction of years. | YEARFRAC(Date2, Date1[, Format]) |

### Database

| Function ID | Description | Syntax |
|:------------|:----------------------------------------------------------------------------------------------------------------|:----------------------------------|
| DAVERAGE | Returns the average of all values in a database field that match the given criteria. | DAVERAGE(Database, Field, Criteria) |
| DCOUNT | Counts the cells containing numbers in a database field that match the given criteria. | DCOUNT(Database, Field, Criteria) |
| DCOUNTA | Counts the non-empty cells in a database field that match the given criteria. | DCOUNTA(Database, Field, Criteria) |
| DGET | Returns the single value from a database field that matches the given criteria. Returns #VALUE! if no records match, and #NUM! if more than one record matches. | DGET(Database, Field, Criteria) |
| DMAX | Returns the maximum value in a database field that matches the given criteria. | DMAX(Database, Field, Criteria) |
| DMIN | Returns the minimum value in a database field that matches the given criteria. | DMIN(Database, Field, Criteria) |
| DPRODUCT | Returns the product of all values in a database field that match the given criteria. | DPRODUCT(Database, Field, Criteria) |
| DSTDEV | Returns the sample standard deviation of all values in a database field that match the given criteria. | DSTDEV(Database, Field, Criteria) |
| DSTDEVP | Returns the population standard deviation of all values in a database field that match the given criteria. | DSTDEVP(Database, Field, Criteria) |
| DSUM | Returns the sum of all values in a database field that match the given criteria. | DSUM(Database, Field, Criteria) |
| DVAR | Returns the sample variance of all values in a database field that match the given criteria. | DVAR(Database, Field, Criteria) |
| DVARP | Returns the population variance of all values in a database field that match the given criteria. | DVARP(Database, Field, Criteria) |

### Engineering

| Function ID | Description | Syntax |
Expand Down
64 changes: 64 additions & 0 deletions docs/guide/integration-with-angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,70 @@ Installing HyperFormula in an Angular application works the same as with vanilla

For more details, see the [client-side installation](client-side-installation.md) section.

## Basic usage
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The framework integration guides should not be modified in this PR


### Step 1. Create a service

Wrap HyperFormula in an Angular service. Create the instance in the constructor and expose methods for reading data.

```typescript
import { Injectable, OnDestroy } from '@angular/core';
import { HyperFormula } from 'hyperformula';

@Injectable({ providedIn: 'root' })
export class SpreadsheetService implements OnDestroy {
private hf: HyperFormula;
private sheetId = 0;

constructor() {
// Create a HyperFormula instance with initial data.
this.hf = HyperFormula.buildFromArray(
[
[10, 20, '=SUM(A1:B1)'],
[30, 40, '=SUM(A2:B2)'],
],
{ licenseKey: 'gpl-v3' }
);
}

/** Return calculated values for the entire sheet. */
getSheetValues(): (number | string | null)[][] {
return this.hf.getSheetValues(this.sheetId);
}

ngOnDestroy(): void {
this.hf.destroy();
}
}
```

### Step 2. Use the service in a component

Inject the service and display the calculated values.

```typescript
import { Component } from '@angular/core';
import { SpreadsheetService } from './spreadsheet.service';

@Component({
selector: 'app-spreadsheet',
template: `
<table>
<tr *ngFor="let row of data">
<td *ngFor="let cell of row">{{ cell }}</td>
</tr>
</table>
`,
})
export class SpreadsheetComponent {
data: (number | string | null)[][];

constructor(private spreadsheet: SpreadsheetService) {
this.data = this.spreadsheet.getSheetValues();
}
}
```

## Demo

Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/angular-demo?v=${$page.buildDateURIEncoded}).
56 changes: 56 additions & 0 deletions docs/guide/integration-with-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,62 @@ Installing HyperFormula in a React application works the same as with vanilla Ja

For more details, see the [client-side installation](client-side-installation.md) section.

## Basic usage

### Step 1. Initialize HyperFormula

Use `useRef` to hold the HyperFormula instance so it persists across re-renders. Initialize it inside a `useEffect` hook.

```javascript
import { useRef, useEffect, useState } from 'react';
import { HyperFormula } from 'hyperformula';

function SpreadsheetComponent() {
const hfRef = useRef(null);
const [sheetData, setSheetData] = useState([]);

useEffect(() => {
// Create a HyperFormula instance with initial data.
hfRef.current = HyperFormula.buildFromArray(
[
[10, 20, '=SUM(A1:B1)'],
[30, 40, '=SUM(A2:B2)'],
],
{ licenseKey: 'gpl-v3' }
);

// Read calculated values from the sheet.
const sheetId = 0;
setSheetData(hfRef.current.getSheetValues(sheetId));

return () => {
// Clean up the instance when the component unmounts.
hfRef.current?.destroy();
};
}, []);
```

### Step 2. Render the results

Display the calculated values in a table.

```javascript
return (
<table>
<tbody>
{sheetData.map((row, rowIdx) => (
<tr key={rowIdx}>
{row.map((cell, colIdx) => (
<td key={colIdx}>{cell}</td>
))}
</tr>
))}
</tbody>
</table>
);
}
```

## Demo

Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/react-demo?v=${$page.buildDateURIEncoded}).
46 changes: 46 additions & 0 deletions docs/guide/integration-with-svelte.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,52 @@ Installing HyperFormula in a Svelte application works the same as with vanilla J

For more details, see the [client-side installation](client-side-installation.md) section.

## Basic usage

### Step 1. Initialize HyperFormula

Create the HyperFormula instance directly in the component's `<script>` block. Use a reactive variable for the results.

```html
<script>
import { HyperFormula } from 'hyperformula';

// Create a HyperFormula instance with initial data.
const hf = HyperFormula.buildFromArray(
[
[10, 20, '=SUM(A1:B1)'],
[30, 40, '=SUM(A2:B2)'],
],
{ licenseKey: 'gpl-v3' }
);

const sheetId = 0;
let data = [];

function calculate() {
data = hf.getSheetValues(sheetId);
}
</script>
```

### Step 2. Render the results

Display the data in a table and trigger calculation with a button.

```html
<button on:click={calculate}>Calculate</button>

<table>
{#each data as row, rowIdx}
<tr>
{#each row as cell, colIdx}
<td>{cell}</td>
{/each}
</tr>
{/each}
</table>
```

## Demo

Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/svelte-demo?v=${$page.buildDateURIEncoded}).
42 changes: 42 additions & 0 deletions docs/guide/integration-with-vue.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,48 @@ Installing HyperFormula in a Vue application works the same as with vanilla Java

For more details, see the [client-side installation](client-side-installation.md) section.

## Basic usage

### Step 1. Initialize HyperFormula

Wrap the HyperFormula instance in `markRaw` to prevent Vue's reactivity system from converting it into a proxy (see [Troubleshooting](#vue-reactivity-issues) below). Use `ref` for the data you want to display.

```javascript
<script setup>
import { ref, markRaw } from 'vue';
import { HyperFormula } from 'hyperformula';

// Create a HyperFormula instance with initial data.
const hf = markRaw(
HyperFormula.buildFromArray(
[
[10, 20, '=SUM(A1:B1)'],
[30, 40, '=SUM(A2:B2)'],
],
{ licenseKey: 'gpl-v3' }
)
);

// Read calculated values from the sheet.
const sheetId = 0;
const data = ref(hf.getSheetValues(sheetId));
</script>
```

### Step 2. Render the results

Display the calculated values in a template.

```html
<template>
<table>
<tr v-for="(row, rowIdx) in data" :key="rowIdx">
<td v-for="(cell, colIdx) in row" :key="colIdx">{{ cell }}</td>
</tr>
</table>
</template>
```

## Troubleshooting

### Vue reactivity issues
Expand Down
2 changes: 2 additions & 0 deletions docs/guide/known-limitations.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ 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.
* DGET returns `#VALUE!` when no records match the criteria, and `#NUM!` when more than one record matches.
* DMAX, DMIN, and DPRODUCT return `0` when no records match the criteria.
Comment on lines +41 to +42
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it listed as limitations? Is it different to what Excel does?

12 changes: 12 additions & 0 deletions src/i18n/languages/csCZ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ const dictionary: RawTranslationPackage = {
DAYS360: 'ROK360',
DAYS: 'DAYS',
DB: 'ODPIS.ZRYCH',
DAVERAGE: 'DPRŮMĚR',
DCOUNT: 'DPOČET',
DCOUNTA: 'DPOČET2',
DGET: 'DZÍSKAT',
DMAX: 'DMAX',
DMIN: 'DMIN',
DPRODUCT: 'DSOUČIN',
DSTDEV: 'DSMODCH.VÝBĚR',
DSTDEVP: 'DSMODCH',
DSUM: 'DSUMA',
DVAR: 'DVAR.VÝBĚR',
DVARP: 'DVAR',
DDB: 'ODPIS.ZRYCH2',
DEC2BIN: 'DEC2BIN',
DEC2HEX: 'DEC2HEX',
Expand Down
12 changes: 12 additions & 0 deletions src/i18n/languages/daDK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ const dictionary: RawTranslationPackage = {
DAYS360: 'DAGE360',
DAYS: 'DAGE',
DB: 'DB',
DAVERAGE: 'DMIDDEL',
DCOUNT: 'DTÆL',
DCOUNTA: 'DTÆLV',
DGET: 'DHENT',
DMAX: 'DMAKS',
DMIN: 'DMIN',
DPRODUCT: 'DPRODUKT',
DSTDEV: 'DSTDAFV',
DSTDEVP: 'DSTDAFVP',
DSUM: 'DSUM',
DVAR: 'DVARIANS',
DVARP: 'DVARIANSP',
DDB: 'DSA',
DEC2BIN: 'DEC.TIL.BIN',
DEC2HEX: 'DEC.TIL.HEX',
Expand Down
12 changes: 12 additions & 0 deletions src/i18n/languages/deDE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ const dictionary: RawTranslationPackage = {
DAYS360: 'TAGE360',
DAYS: 'TAGE',
DB: 'GDA2',
DAVERAGE: 'DBMITTELWERT',
DCOUNT: 'DBANZAHL',
DCOUNTA: 'DBANZAHL2',
DGET: 'DBAUSZUG',
DMAX: 'DBMAX',
DMIN: 'DBMIN',
DPRODUCT: 'DBPRODUKT',
DSTDEV: 'DBSTDABW',
DSTDEVP: 'DBSTDABWN',
DSUM: 'DBSUMME',
DVAR: 'DBVARIANZ',
DVARP: 'DBVARIANZEN',
DDB: 'GDA',
DEC2BIN: 'DEZINBIN',
DEC2HEX: 'DEZINHEX',
Expand Down
12 changes: 12 additions & 0 deletions src/i18n/languages/enGB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ const dictionary: RawTranslationPackage = {
DAYS360: 'DAYS360',
DAYS: 'DAYS',
DB: 'DB',
DAVERAGE: 'DAVERAGE',
DCOUNT: 'DCOUNT',
DCOUNTA: 'DCOUNTA',
DGET: 'DGET',
DMAX: 'DMAX',
DMIN: 'DMIN',
DPRODUCT: 'DPRODUCT',
DSTDEV: 'DSTDEV',
DSTDEVP: 'DSTDEVP',
DSUM: 'DSUM',
DVAR: 'DVAR',
DVARP: 'DVARP',
DDB: 'DDB',
DEC2BIN: 'DEC2BIN',
DEC2HEX: 'DEC2HEX',
Expand Down
12 changes: 12 additions & 0 deletions src/i18n/languages/esES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ export const dictionary: RawTranslationPackage = {
DAYS360: 'DIAS360',
DAYS: 'DÍAS',
DB: 'DB',
DAVERAGE: 'BDPROMEDIO',
DCOUNT: 'BDCONTAR',
DCOUNTA: 'BDCONTARA',
DGET: 'BDEXTRAER',
DMAX: 'BDMAX',
DMIN: 'BDMIN',
DPRODUCT: 'BDPRODUCTO',
DSTDEV: 'BDDESVEST',
DSTDEVP: 'BDDESVESTP',
DSUM: 'BDSUMA',
DVAR: 'BDVAR',
DVARP: 'BDVARP',
DDB: 'DDB',
DEC2BIN: 'DEC.A.BIN',
DEC2HEX: 'DEC.A.HEX',
Expand Down
Loading
Loading