# Formula.js ports Excel functions to JavaScript and documents where the port changes meaning

> Formula.js is a JavaScript implementation of most Microsoft Excel formula functions, published as @formulajs/formulajs, usable from a browser, from Node with either module system, and from a small command line shell. The documentation is candid about the differences, above all that its date functions return real Date objects instead of Excel's serial numbers.

**formulajs/formulajs** — JavaScript implementation of most Microsoft Excel formula functions

- Repository: https://github.com/formulajs/formulajs
- Website: https://formulajs.info/
- Stars: 823 · Forks: 105
- Language: JavaScript
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/formulajs-formulajs

## Excel semantics, ported and partially adjusted

Formula.js is a JavaScript implementation of most Microsoft Excel formula functions, published on npm as @formulajs/formulajs, with the documentation on formulajs.info. The current version is 4.6.1, released on 2026-07-28, after 4.6.0 in April 2026 and 4.5.7 in January 2026, and the last push to the repository was on 2026-10-01.

The licence is listed as a custom licence that GitHub cannot classify, with the details in the LICENSE file at the root of the repository; the package metadata records it as MIT.

The design question for any such library is how faithfully to copy Excel, and Formula.js takes a middle position. The function names, the argument order and the general behaviour follow Excel, so a formula you recognise from a spreadsheet usually reads the same here. The exceptions are documented in a section titled Differences between Excel functions and Formula.js, and the README is explicit that some functions have a different return type rather than a slightly different value.

The repository layout reflects a modern JavaScript package rather than a script collection. There is src/ for the sources, test/ for the mocha suite, bin/ for the command line entry point and the implementation stats script, a rollup.config.js for the build, an eslint config and a Prettier configuration, a tsconfig.json for the type generation, a CHANGES.md and an IMPLEMENTATION_STATS.md. The package is type module, with separate CommonJS and ES module builds and a browser bundle, and the runtime dependencies are just bessel and jstat, the Bessel functions and the statistics library that the mathematical functions need.

## The date functions break the spreadsheet mental model

The single most important difference is the date handling, and the README puts it under its own heading.

The functions DATE, DATEVALUE, EDATE, EOMONT, NOW and TODAY return a plain JavaScript Date instead of the serial Excel number.

The consequence is arithmetic. Copying a composite formula directly from Excel into JavaScript will not work out of the box, and the README gives the example.

```javascript
= DATE(2020,5,9) - DATE(2020,5,8) // Formula.js: 86400000 / Excel: 1
```

In Excel, subtracting two dates gives a number of days. In Formula.js, subtracting two Date objects gives a number of milliseconds, which is 86400000 for a day.

That is not a bug, it is a different type system, and it is the kind of difference that quietly changes results if you port a spreadsheet formula without reading the section. Any code that treats a date as a number, or that formats a result assuming Excel's serial numbering, has to be adjusted.

The second point is about DATEVALUE, and the advice is blunt: it is not recommended to use DATEVALUE to parse a string representing a date, because Formula.js uses new Date('YOUR STRING') under the hood, and there are better libraries for that job, with Moment.js given as an example.

## Three ways in: script tag, module import, and a shell

The distribution is designed to be used from wherever your code runs, and the README shows all three.

In the browser, the package is served by jsDelivr and pulled in with a single script tag.

```html
<script src="https://cdn.jsdelivr.net/npm/@formulajs/formulajs/lib/browser/formula.min.js"></script>
```

The functions are then reachable on a global namespace.

```javascript
formulajs.DATE(2008, 7, 8)
formulajs.SUM([1, 2, 3])
```

In Node, the package installs with npm.

```bash
npm i @formulajs/formulajs
```

And the import styles cover both the whole package and single functions.

```javascript
import * as formulajs from '@formulajs/formulajs' // import entire package

formulajs.SUM([1, 2, 3]) // 6
```

```javascript
import { SUM } from '@formulajs/formulajs' // import individual components

SUM([1, 2, 3]) // 6
```

The same two shapes exist for require, so a CommonJS codebase is not forced to interop with the ES build.

There is also a command line interface. Install the package globally and you get a formulajs command that reads expressions and prints results.

```bash
npm i -g @formulajs/formulajs
```

```sh
$ formulajs
> SUM(1,2,3)
6
```

The package metadata wires the binary to ./bin/cli.js, and the browser bundle is published for both unpkg and jsDelivr, so the same version serves the script tag, the module and the shell.

## Four text functions and four matrix functions went away

The migration guide covers two predecessor packages, and the first one documents actual removals.

If you were previously using formulajs from Sutoiku, some functions have been removed due to dependency simplification. The text functions that are gone are FIXED, TEXT, DOLLAR and VALUE. The math functions that are gone are MDETERM, MINVERSE, MMULT and MUNIT, which are the matrix operations.

The README is clear about the rest: otherwise the two packages are fully compatible and you can swap them.

That is a useful thing to know before you upgrade, because a removed function is a breaking change at runtime rather than at install time. TEXT and VALUE in particular are common in spreadsheet work, TEXT for formatting a number as a string and VALUE for parsing one, and a code base that used them will not fail to build, it will fail when that branch runs.

The second migration path is the Handsontable package. The code of this package is originally forked from @handsontable/formulajs version 2.0.2, released in January 2020, and the two packages were identical at the time. The README states there is no regression, only fixes and new functions since the fork.

## Three forks deep, and detached from its parents in 2023

The history section is unusual and worth reading, because it tells you who to ask and where the behaviour comes from.

The original Formula.js project was developed and maintained by Ismael Chang Ghalimi, with support from Sutoiku and help from contributors including Ilmari Karonen, Sébastien Loisel, Trevor Norris, Roönaän and Hannes Stiebitzhofer. It was then forked and extended by the handsontable/formula.js repository, with contributions mainly from @budnix.

Then, as of September 2023, the repository is officially detached from its Handsontable and Sutoiku origins.

That detachment is the reason the current package is scoped as @formulajs/formulajs rather than the older names, and it is why the migration guide matters. A project that started as one library, was forked into a fork, and then separated from both of its parents has accumulated compatibility questions that the README resolves one at a time.

The implementation coverage question is answered elsewhere in the tree. IMPLEMENTATION_STATS.md at the repository root, together with the stats script at bin/implementation-stats.js, is the place to look for how much of the Excel function surface is covered, and the npm script named stats runs it.

## The build produces three artefacts and a type declaration

The package.json is a good map of the build, and it explains why the library works in browsers, in CommonJS code and in ES module code from one source tree.

The build script runs rollup and then generates the types with tsc, and the prebuild hook runs Prettier, ESLint and the coverage test suite first, so a release cannot skip the checks. The rollup configuration is at rollup.config.js in the root.

The published artefacts are declared in the files array: bin/cli.js, lib and types. The entry points point into three separate trees. main is ./lib/cjs for the CommonJS build, module is ./lib/esm, and the unpkg and jsDelivr fields both point at ./lib/browser/formula.min.js, the minified browser bundle that the script tag loads. The exports map adds the type declarations for each condition, with separate .d.mts and .d.cts files for the ES and CommonJS builds, and a types field at the top level for older tooling.

The test setup is thorough. The unit test workflow and the npm publish workflow both have badges in the README, the suite runs on mocha with a recursive flag, there is a browser variant that uses the mochawesome reporter, coverage runs through c8 with a .nycrc configuration, and there is a watch mode that runs the tests in parallel.

Two runtime dependencies, bessel and jstat, are what make the mathematical and statistical functions possible without a heavier dependency tree, and the README notes the dependency simplification as the reason the matrix functions were dropped.

## Where Formula.js is the wrong tool

Three cases rule it out.

The first is when the output has to match Excel exactly. The date functions returning Date objects instead of serial numbers is not a rounding difference, it is a different result type, and a spreadsheet whose formulas are copied into a report generator will produce different numbers unless the date handling is rewritten. If the contract with the business is that the numbers match what Excel shows, you are maintaining a port of Excel semantics rather than using a convenience library, and you should know that going in.

The second is when you need the functions that were removed. TEXT, VALUE, FIXED, DOLLAR and the four matrix functions are simply not there, and a spreadsheet template that uses them will fail at runtime rather than at install. The fix is a different library or your own implementation, not a version pin, because the removal was a deliberate dependency decision.

The third is a small calculation. A sum, an average and a lookup are a few lines of JavaScript, and adding a dependency with three output shapes and a compatibility history to a project that needs none of that is a cost with no offsetting benefit.

Where it fits, it is a well documented port with a maintained build, a browser bundle, a command line shell for quick checks, and an unusually honest list of where the port diverges from the original.

## Conclusion

Formula.js fits a JavaScript application that has to reproduce a spreadsheet calculation, for example a pricing form, a report generator or a data pipeline with a column of Excel formulas in it, because the function names and argument shapes match what a spreadsheet user expects. It is the wrong tool when the calculation has to be identical to Excel's output, since the date functions return Date objects rather than serial numbers and at least four text functions and four matrix functions were removed for dependency simplification. Before adopting it, read the differences section in the README against the formulas you actually need, and check IMPLEMENTATION_STATS.md for how much of the Excel surface is covered.

## FAQ

### How do I install and use Formula.js in Node?

Run npm i @formulajs/formulajs, then either import the whole package with import * as formulajs from '@formulajs/formulajs' or import single functions such as import { SUM } from '@formulajs/formulajs'. The package also ships a CommonJS build, so require works the same way.

### How does Formula.js differ from Excel for date functions?

The functions DATE, DATEVALUE, EDATE, EOMONT, NOW and TODAY return a plain JavaScript Date instead of the serial Excel number, so subtracting two dates gives milliseconds rather than days. The README also advises against using DATEVALUE to parse a date string, since it uses new Date under the hood.

### Which functions were removed compared with the Sutoiku version of formulajs?

Dependency simplification removed the text functions FIXED, TEXT, DOLLAR and VALUE, and the math functions MDETERM, MINVERSE, MMULT and MUNIT. The README says the two packages are otherwise fully compatible and can be swapped.

### Can I use Formula.js from the browser?

Yes. The README shows a script tag pointing at the jsDelivr build of lib/browser/formula.min.js, after which the functions are available on the formulajs namespace, for example formulajs.SUM([1, 2, 3]).

### Does Formula.js have a command line interface?

Yes. Install it globally with npm i -g @formulajs/formulajs, then run formulajs and type expressions such as SUM(1,2,3), which prints 6. The binary is wired to ./bin/cli.js in the package metadata.

## Sources

- [formulajs/formulajs on GitHub](https://github.com/formulajs/formulajs)
- [Issues](https://github.com/formulajs/formulajs/issues)
- [Project website](https://formulajs.info/)
- [README](https://github.com/formulajs/formulajs/blob/master/README.md)
- [Releases](https://github.com/formulajs/formulajs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/formulajs-formulajs
