From 858fcd5fb684bc240403b8b6f0868cea758ecf88 Mon Sep 17 00:00:00 2001 From: Krzysztof Budnik Date: Tue, 28 Jun 2016 16:56:51 +0200 Subject: [PATCH 1/2] Update README and change package name --- CONTRIBUTING.md | 17 +++++ README.md | 195 +++++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 +- 3 files changed, 211 insertions(+), 4 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..b1c7aaad --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,17 @@ +# Contributing to FormulaParser + +Your contributions to the project are very welcome. If you would like to fix a bug or propose a new feature, you can submit a Pull Request. + +To help us merge your Pull Request, please make sure you follow these points: + +1. Please make your fix on a separate branch based on `develop` branch. This makes merging much easier. +2. Do not edit files in `dist/` directory (e.g: `formula-parser.js`, `formula-parser.min.js`). Instead, edit files inside the `src/` directory and then use `gulp` or `npm scripts` to make a build. +3. **Very important:** For any change that you make, **please try to also add a test case(s)** in `tests/unit/` or `test/integration/`. This helps us understand the issue and make sure that it will stay fixed forever. +5. Describe the problem in the Pull Request description (of course you would do it, why do I mention that?). +6. **Very important:** Make Pull Request ready to merge into `develop` branch. + +Thank you for your commitment! + +## Team rules + +The Handsontable team utilizes Git-Flow. See [How we use Git-Flow](https://github.com/handsontable/handsontable/wiki/How-we-use-Git-Flow) diff --git a/README.md b/README.md index d58e7157..4699adef 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,192 @@ -Formula Parser -======= -Like excel library to parse formulas. +Formula Parser [![Build Status](https://travis-ci.org/handsontable/formula-parser.png?branch=master)](https://travis-ci.org/handsontable/formula-parser) +========== +Library provides a `Parser` class that evaluates excel and mathematical formulas. + +- - - + +## Install + +A recommended way to install Formula Parser is through [NPM](https://www.npmjs.com/) using the following command: + +```sh +$ npm install hot-formula-parser --save +``` + +Node.js: +```js +var FormulaParser = require('hot-formula-parser').Parser; +var parser = new FormulaParser(); + +parser.parse('SUM(1, 6, 7)'); // It returns `Object {error: null, result: 14}` +``` + +Browser: +```html + + +``` +## Features + +It supports: + + * Any numbers, negative and positive as float or integer; + * Arithmetic operations like `+`, `-`, `/`, `*`, `%`, `^`; + * Logical operations like `AND()`, `OR()`, `NOT()`, `XOR()`; + * Comparison operations like `=`, `>`, `>=`, `<`, `<=`, `<>`; + * All JavaScript Math constants like `PI()`, `E()`, `LN10()`, `LN2()`, `LOG10E()`, `LOG2E()`, `SQRT1_2()`, `SQRT2()`; + * String operations like `&` (concatenation eq. `parser.parse('-(2&5)');` will returns `-25`); + * All excel formulas defined in [formula.js](https://github.com/handsontable/formula.js); + * Relative and absolute cell coordinates like `A1`, `$A1`, `A$1`, `$A$1`; + * Build-in variables like `TRUE`, `FALSE`, `NULL` + * Custom variables; + * [TODO] Custom functions/formulas; + * Node and Browser environment. + +## API (methods) + +```js +var parser = new formulaParser.Parser(); +``` + +### .parse(expression) + +Parses and evaluates provided expression. It always returns an object with `result` and `error` properties. `result` property +always keep evaluated value. If error occurs `error` property will be set as: + * `#ERROR!` General error; + * `#DIV/0!` Divide by zero error; + * `#NAME?` Not recognised function name or variable name; + * `#N/A` Indicates that a value is not available to a formula; + * `#NUM!` Occurs when formula encounters an invalid number; + * `#VALUE?` Occurs when one of formula arguments is of the wrong type. + +```js +parser.parse('(1 + 5 + (5 * 10)) / 10'); // returns `Object {error: null, result: 5.6}` +parser.parse('SUM(MY_VAR)'); // returns `Object {error: "#NAME?", result: null}` +parser.parse('1;;1'); // returns `Object {error: "#ERROR!", result: null}` +``` + +### .setVariable(name, value) + +Set predefined variable name which can be visible while parsing formula expression. + +```js +parser.setVariable('MY_VARIABLE', 5); +parser.setVariable('fooBar', 10); + +parser.parse('(1 + MY_VARIABLE + (5 * fooBar)) / fooBar'); // returns `5.6` +``` + +### .getVariable(name) + +Get variable name. + +```js +parser.setVariable('fooBar', 10); + +parser.getVariable('fooBar'); // returns `10` +``` + +### .SUPPORTED_FORMULAS + +List of all supported formulas function. + +```js +require('hot-formula-parser').SUPPORTED_FORMULAS; // An array of formula names +``` + +## API (hooks) + +### 'callVariable' (name, done) + +Fired while retrieving variable. If variable was defined earlier using `setVariable` you can overwrite it by this hook. + +```js +parser.on('callVariable', function(name, done) { + if (name === 'foo') { + done(Math.PI / 2); + } +}); + +parser.parse('SUM(SIN(foo), COS(foo))'); // returns `1` +``` + +### 'callCellValue' (cellCoord, done) + +Fired while retrieving cell value by its label (eq: `B3`, `B$3`, `B$3`, `$B$3`). + +```js +parser.on('callCellValue', function(cellCoord, done) { + // using label + if (cellCoord.label === 'B$6') { + done('hello'); + } + // or using indexes + if (cellCoord.row.index === 5 && cellCoord.row.isAbsolute && cellCoord.column.index === 1 && !cellCoord.column.isAbsolute) { + done('hello'); + } + + if (cellCoord.label === 'C6') { + done(0.75); + } +}); + +parser.parse('B$6'); // returns `"hello"` +parser.parse('B$6&" world"'); // returns `"hello world"` +parser.parse('FISHER(C6)'); // returns `0.9729550745276566` +``` + +### 'callRangeValue' (startCellCoord, endCellCoord, done) + +Fired while retrieving cells range value (eq: `A1:B3`, `$A1:B$3`, `A$1:B$3`, `$A$1:$B$3`). + +```js +parser.on('callRangeValue', function(startCellCoord, endCellCoord, done) { + var data = [ + [1, 2, 3, 4, 5], + [6, 7, 8, 9, 10], + [11, 12, 13, 14, 15], + [16, 17, 18, 19, 20], + ]; + var fragment = []; + + for (var row = startCellCoord.row.index; row <= endCellCoord.row.index; row++) { + var rowData = data[row]; + var colFragment = []; + + for (var col = startCellCoord.column.index; col <= endCellCoord.column.index; col++) { + colFragment.push(rowData[col]); + } + fragment.push(colFragment); + } + + if (fragment) { + done(fragment); + } +}); + +parser.parse('JOIN(A1:E2)'); // returns `"1,2,3,4,5,6,7,8,9,10"` +parser.parse('COLUMNS(A1:E2)'); // returns `5` +parser.parse('ROWS(A1:E2)'); // returns `2` +parser.parse('COUNT(A1:E2)'); // returns `10` +parser.parse('COUNTIF(A1:E2, ">5")'); // returns `5` +``` + +### Want to help? + +Please see [CONTRIBUTING.md](CONTRIBUTING.md). + +### Changelog + +To see the list of recent changes, see [Releases section](https://github.com/handsontable/formula-parser/releases). + +### License + +The MIT License (see the [LICENSE](https://github.com/handsontable/formula-parser/blob/master/LICENSE) file for the full text). + +### Contact + +You can contact us at hello@handsontable.com. diff --git a/package.json b/package.json index 83ffee22..50b587b0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "formula-parser", + "name": "hot-formula-parser", "version": "1.0.0", "description": "Formula parser", "main": "dist/formula-parser.js", @@ -61,6 +61,7 @@ "jison": "^0.4.17", "json-loader": "^0.5.3", "mocha": "^2.3.4", + "proxyquire": "^1.7.9", "sinon": "^1.17.2", "sinon-chai": "^2.8.0", "vinyl-source-stream": "^1.1.0", From c02dfcc38767520fbcd167d5b9a455a75daca627 Mon Sep 17 00:00:00 2001 From: Krzysztof Budnik Date: Tue, 28 Jun 2016 16:57:47 +0200 Subject: [PATCH 2/2] 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50b587b0..1cd9f4bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hot-formula-parser", - "version": "1.0.0", + "version": "1.0.1", "description": "Formula parser", "main": "dist/formula-parser.js", "scripts": {