Coder Social home page Coder Social logo

xlsx-calc's Introduction

 _  _  __    ____  _  _     ___   __   __     ___ 
( \/ )(  )  / ___)( \/ )   / __) / _\ (  )   / __)
 )  ( / (_/\\___ \ )  (   ( (__ /    \/ (_/\( (__ 
(_/\_)\____/(____/(_/\_)   \___)\_/\_/\____/ \___)

Installation

With npm:

npm install xlsx-calc

OR

yarn add xlsx-calc

How to use

Read the workbook with the great js-xlsx lib.

var XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx');

// change some cell value
workbook.Sheets['Sheet1'].A1.v = 42;

// recalc the workbook
var XLSX_CALC = require('xlsx-calc');
XLSX_CALC(workbook);

// recalc options for ignoring erroneous formulas
XLSX_CALC(workbook, { continue_after_error: true, log_error: true })

formulajs integration

npm install --save @formulajs/formulajs

var XLSX_CALC = require('xlsx-calc');

// load your calc functions lib
var formulajs = require('@formulajs/formulajs');

// import your calc functions lib
XLSX_CALC.import_functions(formulajs);

var workbook = {Sheets: {Sheet1: {}}};

// use it
workbook.Sheets.Sheet1.A5 = {f: 'BETA.DIST(2, 8, 10, true, 1, 3)'};
XLSX_CALC(workbook);

// see the result -> 0.6854705810117458
console.log(workbook.Sheets.Sheet1.A5.v);

How to contribute

Read the basic-tests.js.

Run tests

$ npm run test-w

Run webpack

$ npm run dev

write some test like:

//(...)
describe('HELLO', function() {
    it('says: Hello, World!', function() {
        workbook.Sheets['Sheet1'].A1.f = 'HELLO("World")';
        XLSX_CALC(workbook);
        assert.equal(workbook.Sheets['Sheet1'].A1.v, "Hello, World!");
    });
});
//(...)

Register your formula/function in the src/formulas.js file below the commentary "FORMULAS REGISTERED"

  // +---------------------+
  // | FORMULAS REGISTERED |
  // +---------------------+
  var formulas = {
    'FLOOR': Math.floor,
    'COUNTA': counta,
    'IRR': irr,
    'HELLO': hello // <---- Your contribution!!
  };

Write the implementation function below the commentary "THE IMPLEMENTATIONS".

// +---------------------+
// | THE IMPLEMENTATIONS |
// +---------------------+
function hello(name) {
  return name;
}

If everything is OK you will see the mocha out:

  1) XLSX_CALC HELLO says: Hello, World!:

      AssertionError: "World" == "Hello, World!"
      + expected - actual

      -World
      +Hello, World!
      
      at Context.<anonymous> (test/basic-test.js:510:20)

So end with the correct implementation:

// +---------------------+
// | THE IMPLEMENTATIONS |
// +---------------------+
function hello(name) {
  return "Hello, " + name + "!";
}

Now in terminal:

  HELLO
    ✓ says: Hello, World!

  79 passing (75ms)

Give me the balloon watermelon!

Create a pull request

Thx!

Contributors

Made with contributors-img.

MIT LICENSE

Copyright 2017, fabiooshiro

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

xlsx-calc's People

Contributors

beninsydney avatar benkaiser avatar dam0vm3nt avatar dependabot[bot] avatar edmgt avatar etermory avatar fabiooshiro avatar jonathankeebler avatar kyle1297 avatar laucheukhim avatar lukewlms avatar sethjgore avatar thetrevdev avatar tobyhinloopen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

xlsx-calc's Issues

"ref is an error with new formula" error thrown when executing a formula containing a number division by a blank cell

Hi,

When executing a formula containing a number division by a blank cell, it throws "ref is an error with new formula" error even though a checking on blank cell was done; however no similar error shown for a formula containing a number multiplication by blank cell. For example, where A1 is a blank cell and A2 is a formula,

  1. =IF(AND(ISNUMBER(A1),A1<>0),100/A1,"Number cannot be divided by 0")
    => throw error "ref is an error with new formula A2" instead of showing "Number cannot be divided by 0"

  2. =IF(AND(ISNUMBER(A1),A1<>0),100*A1,"Number cannot be 0")
    => cell A2 shows expected "Number cannot be 0"

Btw, thanks for writing this nice xlsx calculator for js :)

function TRANSPOSE not found

Hi,

I have faced a new undefined function but I do not know how to compute this one unfortunately...
the function is TRANSPOSE.
You apply it to a range of cells and the results gives you a range of cells transposed.

If someone has an idea, that would be of great help!

The CONCATENATE function leaves out the last argument

Hi again,

Another issue I face is when I use the CONCATENATE function. The last argument is always omitted and an undefined shows up in its place.

let workbook = {
	Sheets: {
		Sample: {
			A1: { f: 'CONCATENATE( "I", " told", " you ", "10", " times", "." )' },
			A2: { f: 'CONCATENATE( "I", " told", " you ", "10", " times", ".", "" )' },

			B1: { f: 'CONCATENATE( "I", " told", " you ", SUM( 1, 2, 3, 4 ), " times", ".", "" )' },
			B2: { f: 'CONCATENATE( "I", " told", " you ", SUM( 1, 2, 3, SUM( 4 ) ), " times", ".", "" )' },
			B3: { f: 'CONCATENATE( "I", " told", " you ", SUM( 1, 2, 3, SUM( 4 ), 0 ), " times", ".", "" )' }
		}
	}
}

XLSX_CALC( workbook )

console.log( sheet.A1 )	// "I told you 10 timesundefined"
console.log( sheet.A2 )	// "I told you 10 times.undefined"

console.log( sheet.B1 )	// "I told you 10 times.undefined"
console.log( sheet.B2 )	// "I told you NaN times.undefined"
console.log( sheet.B3 )	// "I told you 10 times.undefined"

null is equal 0 in excel

Seems like null value is equal to 0 in excel. I think there is a need for type checking / convertion, but I'm not sure if the cell type information is available.

Function SH33TJSERRX not found

Hi,
I have the following error:
Error: "Summary"!P8: Function preview!SH33TJSERRX not found

In the sheet Summary, I have the function EOMONTH in P8 which is indeed not defined in xlsx-calc, but the error is strange here.
Have anyone encountered it?
[EDIT] After further investigation, it is indeed EOMONTH function. What I do not understand is why it is written like that. It might come from the package js-xlsx. I will check that.

Thanks for the help!

Cannot read property 'calc' of undefined

I'm getting

TypeError: Cannot read property 'calc' of undefined
    at UserRawFnExecutor._if (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:1023:22)
    at UserRawFnExecutor.self.calc (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:662:30)
    at Exp.self.calc (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:386:32)
    at Exp.update_cell_value (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:229:35)
    at Object.exec_formula (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:752:14)
    at RefValue.calc (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:565:25)
    at exec_minus (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:299:37)
    at Exp.self.calc (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:323:9)
    at Exp.update_cell_value (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:229:35)
    at Object.exec_formula (/Users/lukaskoebis/js_excel/node_modules/xlsx-calc/lib/xlsx-calc.js:752:14)

This is my code:

var XLSX = require('xlsx');
var XLSX_CALC = require('xlsx-calc');
var formulajs = require('formulajs');

// import your calc functions lib
XLSX_CALC.import_functions(formulajs);

var workbook = XLSX.readFile('fund.xlsx');

function f() {
  workbook.Sheets['Fund Economics'].C8.v = 30000;
  // recalc the workbook
  XLSX_CALC(workbook);
  return workbook.Sheets['Fund Economics'].W39
}
console.log(workbook.Sheets['Fund Economics'].C8)
console.log(f())

I attached my spreadsheet.

fund.xlsx

Not working with named cell

Hi,
If I use named cell in formula, XLSX_CALC(workbook) throws an error. No problem if I switch to real cells coordinates

Function IFERROR not found

If the sheet contains IFERROR function, xlsx-calc crashes with:

Function IFERROR not found
    at exec_formula (/Users/amitm02/xlsxNode/node_modules/xlsx-calc/xlsx-calc.js:831:17)
    at mymodule (/Users/amitm02/xlsxNode/node_modules/xlsx-calc/xlsx-calc.js:440:7)

Does this library do smart calculations of the formulas?

So for example, if a user changes cell A1 and B1 depends on A1 does it automatically calculate A1 first and then B1?

Or is it just for parsing and executing the cell formula without any dependency tree calculation stuff?

I had a look at the source code of this library and can't find any dependency tree's being built but I just wanted to make sure.

Basically I'm using hyperformula right now to have quick calculations: https://handsontable.github.io/hyperformula/

And wondering if I can just use this library instead of it.

Show worksheet name in the error message

I started playing with some files and came across the first missing function

Error: D145: Function INDEX not found

The point of this issue isn't the missing function, it's the error message. The message shows that the offending cell is D145 but does not tell me what worksheet the cell was from.

I would suggest showing an error like:

Error: "Worksheet 1"!D145: Function INDEX not found

function MEDIAN not found

Hi,
I have worked on an excel sheet and have the MEDIAN function not found.
I have added it lign 1094:
'MEDIAN':median

and then:


function median() {
if(arguments.length ===0) return 0;

[].slice.call(arguments).sort(function(a,b){
    return a-b;
  });

  let half = Math.floor(arguments.length / 2);

  if (arguments.length % 2)
    return arguments[half];

  return (arguments[half - 1] + arguments[half]) / 2.0;
}

However, I have now the following error but not sure it is linked:

<--- Last few GCs --->

[20192:027F5610]    70524 ms: Mark-sweep 698.2 (723.9) -> 697.8 (723.9) MB, 240.0 / 0.0 ms  (average mu = 0.161, current mu = 0.150) allocation failure scavenge might not succeed
[20192:027F5610]    71105 ms: Mark-sweep 698.6 (723.9) -> 697.8 (723.9) MB, 576.0 / 0.0 ms  (average mu = 0.072, current mu = 0.009) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 2115209E]
    1: StubFrame [pc: 21152FD0]
Security context: 0x21392705 <JSObject>
    2: /* anonymous */ [3A16E6C9] [C:\Users\sperney\Documents\Travail\js-scripts\node_modules\xlsx-calc\lib\xlsx-calc.js:~424] [pc=40324148](this=0x2492ac69 <Range map = 259C8571>)
    3: /* anonymous */ [2492AC15] [C:\Users\sperney\Documents\Travail\js-scripts\node_modules\xlsx-calc\lib\xlsx-calc.js:386] [bytecode=3BAB0BB5 offset=317](...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 00E48A2E node::MakeCallback+3982
 2: 0147BDE2 v8::internal::Heap::MaxHeapGrowingFactor+8146
 3: 01473051 v8::internal::ScavengeJob::operator=+14849
 4: 0147A74E v8::internal::Heap::MaxHeapGrowingFactor+2366

If you know where it could come from, I would be very interested. I think it comes from the median formulas, but not sure.

Calculating across Sheets

Hi @fabiooshiro,

I just came across this great lib, however I found out that this cannot handle calculations between Sheets. What do you think, could it be somehow possible? If so how?

Thanks in advance.

Spaces after parentheses don't work

    it('calcs form with space after parentheses', function() {
        workbook.Sheets.Sheet1.A1.f = '(1) *2';
        XLSX_CALC(workbook);
        assert.equal(workbook.Sheets.Sheet1.A1.v, 2);
    });

This fails with undefined.

Formula Value
1 * 2 2
1 * (2) 2
(1)* 2 2
(1)*2 2
(1) *2 undefined
(1) * 2 undefined

OFFSET function cannot work with current parser

I'm trying to use a spreadsheet that contains a formula like this: =OFFSET(B15,1,0)
I added a custom function called OFFSET that can take 3 variables and compute the new cell reference. But what I found was that B15 was being computed and the result was passed to my offset function.

Here's the code that I wrote:

XlsxCalc.import_functions({
  OFFSET: function() {
    console.log('OFFSET', arguments);
    process.exit(1);
  },
});
XlsxCalc(workbook);

Here's what I expected:

$ node index.js financing.xlsx
OFFSET { '0': 'B15', '1': 1, '2': 0 }

Here's what I got:

$ node index.js financing.xlsx
OFFSET { '0': 'RATE', '1': 1, '2': 0 }

This is because RATE is the value of B15.

I think that OFFSET would require a special case to fix this. We would need to be able to allow functions to specify which of their params should be passed "raw" or "uncomputed".

Support for Sheet with spaces in name

Hello !
First thanks a lot for doing this library.

I have a small issue with one of my files, some the sheets have names with spaces, that are put between '. For example : ='This is a sheet'!$F$4*L267*1.04 Will make the software crash.

I have try to fix it myself, by changing exec_formula.js, function build_expression like this :

    formula.status = 'working';
    var root_exp;
    var str_formula = formula.cell.f;
    if (str_formula[0] == '=') {
        str_formula = str_formula.substr(1);
    }
    var exp_obj = root_exp = new Exp(formula);
    var buffer = '',
        is_string = false,
        was_string = false,
        is_string_spreadsheet = false
        ;

    var fn_stack = [{
        exp: exp_obj
    }];
    for (var i = 0; i < str_formula.length; i++) {
        if (str_formula[i] == '"' || str_formula[i] == "'") {
            is_string_spreadsheet = str_formula[i] == "'"
            if (is_string) {
                if (is_string_spreadsheet) {
                    exp_obj.push(buffer);
                } else {
                    exp_obj.push(new RawValue(buffer));
                }

It made the parsing go a bit further, but crash when evaluating some function :

In Exp.js :

    function checkVariable(obj) {
        if (typeof obj.calc !== 'function') {
            throw new Error('Undefined ' + obj);
        }
    }

I guess somehow the lib does not recognize the call to the sheet. The formula that crash is this one:

='This is a sheet'!$F$4*L267*1.04

I'm going to continue investigating that, but if you have any pointers that might help, would be super cool.

Thanks again for this library !

"Too Much Recursion" error

Recalculating a spreadsheet of moderate complexity will crash the plugin.

Stack trace:

InternalError: "too much recursion"
    push webpack-internal:///./node_modules/xlsx-calc/src/Exp.js:195
    add_operation webpack-internal:///./node_modules/xlsx-calc/src/expression_builder.js:100
    start webpack-internal:///./node_modules/xlsx-calc/src/expression_builder.js:116
    expression_builder webpack-internal:///./node_modules/xlsx-calc/src/expression_builder.js:131
    build_expression webpack-internal:///./node_modules/xlsx-calc/src/exec_formula.js:47
    exec_formula webpack-internal:///./node_modules/xlsx-calc/src/exec_formula.js:51
    calc webpack-internal:///./node_modules/xlsx-calc/src/RefValue.js:48
    exec webpack-internal:///./node_modules/xlsx-calc/src/Exp.js:79
    calc webpack-internal:///./node_modules/xlsx-calc/src/Exp.js:136
    update_cell_value webpack-internal:///./node_modules/xlsx-calc/src/Exp.js:26
    exec_formula webpack-internal:///./node_modules/xlsx-calc/src/exec_formula.js:52
vue.runtime.esm.js:1887:13

issue with sumproduct

Hi,

The sumproduct can be written this way in Excel:
SUMPROD(A1:A4;D1:D4).
But it can also be written like that:
SUMPROD((A1:A4)*D1:D4).

The result is the same in excel but it returns an error with the library as the argument length is 1.
Doing SUM simply on (A1:A4)*D1:D4 does not work unfortunately.
Would there be a way to create a special case if arguments.length===1 then it would be needed to parse the arguments and look for a * and then return sumproduct with the new arguments being the ranges but separated.

XLSX_CALC(workbook) fails with cross-file reference formulas

Hey,
I am trying to evaluate xlsx-calc library for use in production.
Implementing a small POC for this here.

I have 2 files with cells in both files referencing each other (different cells, no infinite dependency).

workbook.Sheets object is this:

{
  TEST: {
    '!ref': 'A2:D4',
    A2: { t: 'n', v: 140, w: '40' },
    B2: { t: 'n', v: 106, f: 'A2+66', w: '106' },
    C2: { t: 'n', v: 60, f: '[1]SHEET1!$A$2+10', w: '60' },
    D2: { t: 'n', v: 200, w: '200' },
    A4: { t: 'n', v: 400, w: '400' },
    B4: { t: 'n', v: 410, f: 'A4+10', w: '410' }
  }
}

Here, TEST sheet's cell C2 is depending on Cell A2 from another file's worksheet SHEET1.
I am not sure if the library is reading the full path of the other file in the formula, correctly?

Actual formula looks like this in the excel:

='FILE_NAME_PATH/[file1.xlsx]SHEET1'!$A$2+10

Could you please help me out with this?

change function interface to support string/numeric type

�This is a really cool library! 👍

I was playing around with the tonic demo and noticed that xlsx-calc was not setting cell types. Some functions return strings (REPT("foo",3) evaluates to the text foofoofoo) and others return numbers (1+1). xlsx-calc should set the type t as well as the value v for cells.

Yes, it is possible to check every cell and assign a type, but excel will generate an error if you try to use the wrong type of variable or reference in some functions.

PS Here's the test code I wrote to experiment with a few features, feel free to adapt:

var XLSX_CALC = require("xlsx-calc");

/* make workbook */
var workbook = { "SheetNames": [], "Sheets": {} };

/* first worksheet */
var sheet1 = {};
sheet1['A1'] = { f:"2+2", t:'n'}; // simple arithmetic
sheet1['A2'] = { f:"3-A1", t:'n'}; // simple cell reference
sheet1['B1'] = { f:"2*ABS(A2)", t:'n'}; // formula
sheet1['B2'] = { f:"AVERAGE(A1:A2,B1)", t:'n', z:'0.00'}; // range reference
sheet1['!ref'] = 'A1:B2'; // set worksheet range

/* add first sheet to workbook */
workbook.SheetNames.push("Sheet1");
workbook.Sheets["Sheet1"] = sheet1;

/* second worksheet */
var sheet2 = {};
sheet2['A1'] = { f:"SUM(Sheet1!A1:B2)", t:'n' } // cross-sheet reference
sheet2['!ref'] = 'A1:A1';

/* add second sheet to workbook */
workbook.SheetNames.push("Sheet2");
workbook.Sheets["Sheet2"] = sheet2;

/* calculate */
XLSX_CALC(workbook);

/* generate CSV for first worksheet */
var XLSX = require('xlsx');
console.log(XLSX.utils.sheet_to_csv(workbook.Sheets.Sheet1));

/* check value of the cross-sheet formula */
console.log(workbook.Sheets.Sheet2.A1.v);

Function CONCAT not found

When CONCAT is used in excel instead of CONCATENATE (or any localized version, which works), xlsx-calc raises an error, where excel understands.

functions OR, round, roundup, choose not found

Hi,
The OR, round, roundup, choose functions are not coded. Here are piece of code that I used, maybe it can be improved?

function or(){
    let temp = false;
    [].slice.call(arguments).forEach((value,key)=>{
        if (value) temp=true
    })
    return temp
}

function round(){

    if(arguments.length ===0) return 0;
    
    let value = [].slice.call(arguments)[0];
    let roundMeasure = Math.pow(10,[].slice.call(arguments)[1]);


    return Math.round(roundMeasure*value)/roundMeasure
}

function roundup(){

    if(arguments.length ===0) return 0;
    
    let value = [].slice.call(arguments)[0];
    let roundMeasure = Math.pow(10,[].slice.call(arguments)[1]);


    return Math.ceil(roundMeasure*value)/roundMeasure
}

Unfortunately I do not know for the choose function...

INDIRECT function

Hi,

I understand that we can register new functions in formulas.js.

I am having issues trying to implement the INDIRECT function. Any tips would be greatly appreciated ? Probably just need INDIRECT("A2").

function SUMIF not found

Hi @fabiooshiro ,

I tried the following for the sumif function but I must admit it is not very clean:

function sumif(){

    let elementToSum = arguments[1];
    let sumResult = 0;

    [].slice.call(arguments)[0][0].forEach((elt,key) =>{

        if (elt!==null){
            if( elt.replace(/\'/g, "") === elementToSum){
                if (!isNaN([].slice.call(arguments)[2][0][key])){
                    sumResult += [].slice.call(arguments)[2][0][key]
                } 
            }
        }
    });
    return sumResult
}

first arg is the range to be checked
second arg is the element to be checked
third arg is the range to be summed.

NPM version is outdated

Hello, I was using the xlsx-calc from NPM and was having an error related to .calc() function.
Investigating the code with my leader, we noticed the NPM package is outdated because when I used the version from the Github, the code worked correctly.

Could you please update the package on NPM?

Thanks in advance.

Cir Ref

Hi again thanks for your work and your help in advance.

I have the following Object

{ "B4": { "t": "s", "v": "A", "r": "<t>A</t>", "h": "A", "z": "General", "w": "A", "s": { "patternType": "none" } }, "C4": { "t": "n", "v": 1, "z": "General", "w": "1", "s": { "patternType": "none" } }, "D4": { "t": "n", "v": 2, "z": "General", "w": "2", "s": { "patternType": "none" } }, "E4": { "t": "n", "v": 3, "z": "General", "w": "3", "s": { "patternType": "none" } }, "G4": { "t": "n", "v": 0.05, "z": "0%", "s": { "patternType": "none" }, "w": "5%" }, "H4": { "t": "n", "v": 3.12, "f": "INDEX(B4:H4,4)", "z": "General", "s": { "patternType": "none" }, "w": "3.12" } }
Change in G4 gives me circular ref error, but it works on Excel.

I think its because Range.js currently works with the ranges as if they are all related. But for certain lookup functions e.g. Vlookup, index, match... etc, its only ever ref to 1 cell and not the whole range.

Also just wondering, is there a way to determine the in str_2_val or other files to check the function first and returns a different Range Object ? The reason is because, if I have vlookup of a large range, creating the array (matrix) could take a long time. But for these look up functions, I do not need the whole range but just possiblly 2 columns or rows.

Thanks for your help.

Missing License File

Hi,

Great work here - but I noticed there's no license file currently in the repository.
Could you add one or indicate somewhere in the README?

Cheers,
Ralph

`match` function does not implement array of non string values

In formula.js, function match( l.147 )
if matchType is 0, the function does not support values as array, if value is not a string.
I Implemented it by doing that :

            if (typeof lookupValue === 'string') {
                lookupValue = lookupValue.replace(/\?/g, '.');

                if (Array.isArray(matrix[idx])) {
                    if (matrix[idx].length === 1
                        && typeof matrix[idx][0] === 'string') {
                            if (matrix[idx][0].toLowerCase() === lookupValue.toLowerCase()) {
                                return idx + 1;
                            }
                        } 
                } else if (typeof matrix[idx] === 'string') {
                    if (matrix[idx].toLowerCase() === lookupValue.toLowerCase()) {
                        return idx + 1;
                    }
                }
            } else {
                if (Array.isArray(matrix[idx])) {
                  if (matrix[idx].length === 1) {
                    if (matrix[idx][0] === lookupValue) {
                      return idx + 1;
                    }
                  }
                } else if (matrix[idx] === lookupValue) {
                    return idx + 1;
                }
            }

Undefined Variable Error

Hi, I am using this code snippet to test the re-calculation of my workbook. I am, however, getting an "Undefined Variable" error.
Is there any chance you could have a quick look at my XLSX file? Thanks in advance.

var XLSX = require('xlsx');
var XLSX_CALC = require('xlsx-calc');
var workbook = XLSX.readFile('./sample.xlsx');
XLSX_CALC(workbook);
console.log(workbook.Sheets['Kalkulator_1'].C29);`
/var/www/excel_experiments/node_modules/xlsx-calc/src/Exp.js:51
                throw e;
                ^

Error: Undefined Verpackungsspielraum
    at checkVariable (/var/www/excel_experiments/node_modules/xlsx-calc/src/Exp.js:64:19)
    at exec (/var/www/excel_experiments/node_modules/xlsx-calc/src/Exp.js:78:25)
    at Exp.self.calc (/var/www/excel_experiments/node_modules/xlsx-calc/src/Exp.js:133:9)
    at Exp.update_cell_value (/var/www/excel_experiments/node_modules/xlsx-calc/src/Exp.js:26:35)
    at Object.exec_formula (/var/www/excel_experiments/node_modules/xlsx-calc/src/exec_formula.js:52:14)
    at RefValue.calc (/var/www/excel_experiments/node_modules/xlsx-calc/src/RefValue.js:48:25)
    at exec (/var/www/excel_experiments/node_modules/xlsx-calc/src/Exp.js:79:48)
    at Exp.self.calc (/var/www/excel_experiments/node_modules/xlsx-calc/src/Exp.js:148:9)
    at UserRawFnExecutor._if (/var/www/excel_experiments/node_modules/xlsx-calc/src/formulas-raw.js:45:19)
    at UserRawFnExecutor.self.calc (/var/www/excel_experiments/node_modules/xlsx-calc/src/UserRawFnExecutor.js:9:34)

calculation is done sheet by sheet

Hi,
Thanks for the package, it is very usefull. However, I noticed that when updateting a parameter from a page, it does not recompute the priori sheets.
For example, a spreadsheet with 2 sheets. If you change a value in sheet 2, the formula of sheet1 which depends on values of sheet2 are not updated.
Maybe you can loop twice on all the cells to do the computation to be sure that they are all updated?
If I change a value of a cell in sheet1, the linked cells with formulas in sheet1 are well updated.
thanks,

[EDIT]: actually I think that the problem comes from the inter-sheet formulas. It seems it is not possible to make the formula works when there are numbers coming from different sheets

Nested functions do not work as expected

Hi,

Thanks for this awesome lib!
I'm having a little trouble when I nest functions in formulas.
I've attached a code snippet demonstrating the issue.

let workbook = {
	Sheets: {
		Sample: {
			B1: { f: 'SUM( 1, 2, 3, 4 )' },
			B2: { f: 'SUM( 1, 2, 3, SUM( 4 ) )' },
			B3: { f: 'SUM( 1, 2, 3, SUM( 4 ), 0 )' },
			B4: { f: 'SUM( 1, 2, 3, SUM( 4, SUM( 5 ) ) )' },
			B5: { f: 'SUM( 1, 2, 3, SUM( 4, SUM( 5 ), 0 ), 0 )' }
		}
	}
}

XLSX_CALC( workbook )

console.log( sheet.B1 )	// 10
console.log( sheet.B2 )	// NaN
console.log( sheet.B3 )	// 10
console.log( sheet.B4 )	// NaN
console.log( sheet.B5 )	// 15

Defined Name Issue

Hi. I'm not sure if this is a problem with xlsx-calc or with xlsx library but I'm not able to handle defined names for cells or ranges.

const xlsx = require('xlsx')
const xlsx_calc = require('xlsx-calc')
const formulajs = require('formulajs')

xlsx_calc.import_functions(formulajs)

const workbook = xlsx.readFile('filename')

const calcd = xlsx_calc(workbook)

throws an error,

{"error":{},"level":"error","message":"uncaughtException: Undefined NBHDJ\nError: Undefined NBHDJ\n    at checkVariable (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:228:19)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:236:21)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:302:9)\n    at exec_minus (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:254:38)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:268:9)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:238:44)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:281:9)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:238:44)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:278:9)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:238:44)","stack":"Error: Undefined NBHDJ\n    at checkVariable (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:228:19)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:236:21)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:302:9)\n    at exec_minus (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:254:38)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:268:9)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:238:44)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:281:9)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:238:44)\n    at Exp.self.calc (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:278:9)\n    at exec (/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js:238:44)","exception":true,"date":"Tue Jan 29 2019 16:36:27 GMT-0600 (Central Standard Time)","process":{"pid":12726,"uid":1000,"gid":1000,"cwd":"/home/administrator/Documents/equity-grids-2019","execPath":"/usr/local/n/versions/node/11.4.0/bin/node","version":"v11.4.0","argv":["/usr/local/n/versions/node/11.4.0/bin/node","/home/administrator/Documents/equity-grids-2019/app.js"],"memoryUsage":{"rss":196091904,"heapTotal":124727296,"heapUsed":101315992,"external":25369145}},"os":{"loadavg":[2.5673828125,2.44921875,2.46728515625],"uptime":348172},"trace":[{"column":19,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"checkVariable","line":228,"method":null,"native":false},{"column":21,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"exec","line":236,"method":null,"native":false},{"column":9,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"Exp.self.calc","line":302,"method":"calc","native":false},{"column":38,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"exec_minus","line":254,"method":null,"native":false},{"column":9,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"Exp.self.calc","line":268,"method":"calc","native":false},{"column":44,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"exec","line":238,"method":null,"native":false},{"column":9,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"Exp.self.calc","line":281,"method":"calc","native":false},{"column":44,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"exec","line":238,"method":null,"native":false},{"column":9,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"Exp.self.calc","line":278,"method":"calc","native":false},{"column":44,"file":"/home/administrator/Documents/equity-grids-2019/node_modules/xlsx-calc/lib/xlsx-calc.js","function":"exec","line":238,"method":null,"native":false}]}

Incompatible implementations in formula.js

Hi everyone,

some functions from formula.js need an incompatible type to return the expected result, for example:

MATCH impl expects an array of values, where xlsx will provide a Range (array of arrays), so MATCH will throw an error in our case.

I'm willing to make a PR fixing that issue, but i'm currently wondering which solution would be better.
If i modified XLSX_CALC.import_functions to not override formulas explicitely defined by XLSX_CALC, would that be an acceptable solution ? If not, how would you do ?

anyhow thanks for the cool lib !

Cell with no value but used in a formula throws "Cell '[full-name-ref]' not found"

Hi @fabiooshiro !
I'm using xlsx-js to parse and write some values in a multiple sheets workbook which contains formulas that I need to recompute right after the value of a cell has been modified, then parse the new value and inject it somewhere else.

Sometimes, formulas use cells with no values, checked with "IF(ISBLANK())".
In that case, I get the Error : Cell '[full-name-ref]' not found.

Do you have any idea how to fix that ?

Thanks !

Cannot read property 'f' of undefined

code breaks if some cell is undefined.

TypeError: Cannot read property 'f' of undefined at find_all_cells_with_formulas (f:\projects\upgraded\platalyticsfrontend\node_modules\xlsx-calc\lib\xlsx-calc.js:825:34) at mymodule (f:\projects\upgraded\platalyticsfrontend\node_modules\xlsx-calc\lib\xlsx-calc.js:1554:20) at test (f:\projects\upgraded\platalyticsfrontend\controllers\dataWranglerController.js:163:9) at Layer.handle [as handle_request] (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\layer.js:95:5) at next (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\route.js:137:13) at Route.dispatch (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\route.js:112:3) at Layer.handle [as handle_request] (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\layer.js:95:5) at f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:281:22 at Function.process_params (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:335:12) at next (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:275:10) at Function.handle (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:174:3) at router (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:47:12) at Layer.handle [as handle_request] (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\layer.js:95:5) at trim_prefix (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:317:13) at f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:284:7 at Function.process_params (f:\projects\upgraded\platalyticsfrontend\node_modules\express\lib\router\index.js:335:12)

Multiple Sheets Calculation

Love your work, but just encounter a weird issue.

My object is the following
{ "Sheet1": { "!ref": "B3:B5", "B3": { "t": "n", "v": 30, "z": "General", "w": "30" }, "B4": { "t": "n", "v": 60, "f": "20+Sheet2!B3", "z": "General", "w": "60" }, "B5": { "t": "n", "v": 90, "f": "SUM(B3:B4)", "z": "General", "w": "90" }, "!margins": { "left": 0.7, "right": 0.7, "top": 0.75, "bottom": 0.75, "header": 0.3, "footer": 0.3 } }, "Sheet2": { "B3": { "t": "n", "v": 40, "f": "10+Sheet1!B3", "z": "General", "w": "40" }, "!margins": { "left": 0.7, "right": 0.7, "top": 0.75, "bottom": 0.75, "header": 0.3, "footer": 0.3 }, "!ref": "B3" } }

Where (B4 of Sheet 1) is dependent on (B3 of Sheet 2).
(B3 of Sheet 2) is dependent on (B3 of Sheet 1)
and (B5 of Sheet1) is the sum of B3-B4 of Sheet 1.

So if I update (B3 of Sheet1) it should update all the cells in the object. But I notice (B5 of Sheet 1), which is the sum, does not update.
Not sure if I am doing anything wrong? let me know

Thanks.

function CORREL not found

Hi,
The correl function does not exists:

I have taken the covariance function and modified it to compute the correlation:

function correl(a,b){

    a = getArrayOfNumbers(a);
    b = getArrayOfNumbers(b);

    if (a.length !== b.length) {
        return 'N/D';
    }
    var inv_n = 1.0 / (a.length-1);
    var avg_a = sum.apply(this, a) / a.length;
    var avg_b = sum.apply(this, b) / b.length;
    var s = 0.0;
    var sa = 0;
    var sb=0;
    for (var i = 0; i < a.length; i++) {
        s += (a[i] - avg_a) * (b[i] - avg_b);

        sa+=Math.pow(a[i],2);
        sb+=Math.pow(b[i],2);
    }

    sa=Math.sqrt(sa/inv_n);
    sb=Math.sqrt(sb/inv_n);

    return s / (inv_n*sa*sb);
}

How to implement asynchronous UDF's

Hi there,

Great library, I'm a big fan. I've got to the stage where I'de like to implement a few UDF which equate to restful API requests. Now ideally I'de like to use my already existing API client which is run via promises. I was wondering how it could be possible to extend the code to enable such a feature.

I guess I'd need to promify methods like update_cell_value, the calculator class execute method and any method which contains formula.exec_formula. Do you have any recommendations or advice for this idea?

[EDIT] I just noticed their is a promise branch. Is this branch working?

IF condition get transformed into TRUE, and fails

Some oddity,

I have a cell with a formula : =IF(L4=1,L464,0)
L4 is a Number cell, with this formula : =$Inputs.N4<>""

When using the library,
=IF(L4=1,L464,0) get transformed ( from the debugger ) to =IF(L4=TRUE,L464,0)
And the library assert with Error: Undefined TRUE with this callstack :

Error: Undefined TRUE
    at checkVariable (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:268:19)
    at exec (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:282:25)
    at Exp.self.calc (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:367:9)
    at UserRawFnExecutor._if (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:1018:19)
    at UserRawFnExecutor.self.calc (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:657:30)
    at Exp.self.calc (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:381:32)
    at Exp.update_cell_value (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:230:35)
    at exec_formula (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:763:14)
    at mymodule (/home/olivier/Downloads/test/node_modules/xlsx-calc/lib/xlsx-calc.js:1747:9)
    at Object.<anonymous> (/home/olivier/Downloads/test/index.js:15:1)

I have tried to reproduce this in a simple sheet, but was not able to. Still investigating.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.