是否有一个JavaScript库可以在没有UI的情况下进行电子表格计算

Is there a javascript library that does spreadsheet calculations without the UI

本文关键字:情况下 UI 计算 电子表格 JavaScript 有一个 是否      更新时间:2023-09-26

我正在做一个项目,该项目需要在浏览器中使用类似 excel 的计算引擎。但是,它不需要网格 UI。

目前,我可以通过隐藏Handsontable的"div"元素来做到这一点。但是,它并不优雅。它也有点慢。

javascript 中是否有一个客户端电子表格计算库可以做这样的事情?

x = [ [1, 2, "=A1+B1"],
      [2, "=SUM(A1,A2"),3] ];
y = CalculateJS(x);
##############
y: [[1, 2, 3], 
[2,3,3]]
我不知道

(虽然我还没有真正看过),但是如果你想实现自己的,你可以按照这些思路做一些事情(严重未优化,没有错误检查):

functions = {
    SUM: function(args) {
        var result = 0;
        for (var i = 0; i < args.length; i++) {
            result += parseInt(args[i]);
        }
        return result;
    }
};
function get_cell(position) {
    // This function returns the value of a cell at `position`
}
function parse_cell(position) {
    cell = get_cell(position);
    if (cell.length < 1 || cell[0] !== '=')
        return cell;
    return parse_token(cell.slice(1));
}
function parse_token(tok) {
    tok = tok.trim();
    if (tok.indexOf("(") < 0)
        return parse_cell(tok);
    var name = tok.slice(0, tok.indexOf("("));
    if (!(name in functions)) {
        return 0; // something better than this?
    }
    var arguments_tok = tok.slice(tok.indexOf("(") + 1);
    var arguments = [];
    while (true) {
        var arg_end = arguments_tok.indexOf(",");
        if (arg_end < 0) {
            arg_end = arguments_tok.lastIndexOf(")");
            if (arg_end < 0)
                break;
        }
        if (arguments_tok.indexOf("(") >= 0 && (arguments_tok.indexOf("(") < arg_end)) {
            var paren_amt = 1;
            arg_end = arguments_tok.indexOf("(") + 1;
            var end_tok = arguments_tok.slice(arguments_tok.indexOf("(") + 1);
            while (true) {
                if (paren_amt < 1) {
                    var last_index = end_tok.indexOf(",");
                    if (last_index < 0)
                        last_index = end_tok.indexOf(")");
                    arg_end += last_index;
                    end_tok = end_tok.slice(last_index);
                    break;
                }
                if (end_tok.indexOf("(") > 0 && (end_tok.indexOf("(") < end_tok.indexOf(")"))) {
                    paren_amt++;
                    arg_end += end_tok.indexOf("(") + 1;
                    end_tok = end_tok.slice(end_tok.indexOf("(") + 1);
                } else {
                    arg_end += end_tok.indexOf(")") + 1;
                    end_tok = end_tok.slice(end_tok.indexOf(")") + 1);
                    paren_amt--;
                }
            }
        }
        arguments.push(parse_token(arguments_tok.slice(0, arg_end)));
        arguments_tok = arguments_tok.slice(arg_end + 1);
    }
    return functions[name](arguments);
}

希望这能给你一个起点!

若要在浏览器中进行测试,请将"get_cell"设置为 function get_cell(x) {return x;} ,然后运行 parse_cell("=SUM(5,SUM(1,7,SUM(8,111)),7,8)") 。它应该导致147 :)

我设法使用培根.js做到这一点。它解释了细胞的相互依赖性。截至目前,它通过使用 eval 函数计算 javascript 公式而不是 excel 公式的值。要使其适用于excel公式,所要做的就是用Handsontable的ruleJS库替换eval。我找不到该库的 URI...因此,埃瓦尔。

https://jsfiddle.net/sandeep_muthangi/3src81n3/56/

var mx = [[1, 2, "A1+A2"],
        [2, "A2", "A3"]];
var output_reference_bus = {};
var re = /'$?[A-N]{1,2}'$?[1-9]{1,4}/ig
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('');
function convertToCellRef(rows, cols)   {
    var alphabet_index = rows+1, 
        abet = "";
  while (alphabet_index>0)  {
    abet = alphabet[alphabet_index%alphabet.length-1]+abet;
    alphabet_index = Math.floor(alphabet_index/alphabet.length);
  }
  return abet+(cols+1).toString();
}
function getAllReferences(value)    {
    if (typeof value != "string")
    return null;
  var references = value.match(re)
  if (references.length == 0)
    return null;
  return references;   
}
function replaceReferences(equation, args)  {
    var index = 0;
    return equation.replace(re, function(match, x, string)  {       
      return args[index++];
  });
}
//Assign an output bus to each cell
mx.forEach(function(row, row_index) {
    row.forEach(function(cell, cell_index)  {
    output_reference_bus[convertToCellRef(row_index, cell_index)] = Bacon.Bus();    
  })
})
//assign input buses based on cell references... and calculate the result when there is a value on all input buses
mx.forEach(function(row, row_index) {
    row.forEach(function(cell, cell_index)  {    
    if ((all_refs = getAllReferences(cell)) != null)    {
        var result = Bacon.combineAsArray(output_reference_bus[all_refs[0]]);
      for (i=1; i<all_refs.length; i++) {           
        result = Bacon.combineAsArray(result, output_reference_bus[all_refs[i]]);
      }
      result = result.map(function(data)    {           
            return eval(replaceReferences(cell, data));
      })      
      result.onValue(function(data) {
        console.log(convertToCellRef(row_index, cell_index), data);
        output_reference_bus[convertToCellRef(row_index, cell_index)].push(data);        
      });
    }
   else {
    if (typeof cell != "string")
      output_reference_bus[convertToCellRef(row_index, cell_index)].push(cell);          
    else        
      output_reference_bus[convertToCellRef(row_index, cell_index)].push(eval(cell));
   }
  })
})
output_reference_bus["A2"].push(20);
output_reference_bus["A1"].push(1);
output_reference_bus["A1"].push(50);
相关文章: