是否有一个JavaScript库可以在没有UI的情况下进行电子表格计算
Is there a javascript library that does spreadsheet calculations without the UI
我正在做一个项目,该项目需要在浏览器中使用类似 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);
相关文章:
- 从技术上讲,是否可以在不拥有页面UI的情况下删除页面UI的某些部分
- Angular UI Router-在不了解第二级嵌套视图的情况下更改第三级嵌套视图
- Angular/UI路由器-如何在不刷新所有内容的情况下更新URL
- 仅在尚未运行jQuery UI的情况下运行动画
- 如何在不创建数组的情况下使用NgFor来生成矩阵UI模式
- 是否有一个JavaScript库可以在没有UI的情况下进行电子表格计算
- UI 路由加载微调器在没有$timeout的情况下不起作用
- UI 路由器在不更改 url 的情况下更改状态
- Windows 8商店应用程序在没有特殊UI的情况下捕获视频/照片
- ui-router:在不使用 $state.go() 的情况下重置$state
- 如何在“后台”/不冻结UI的情况下运行javascript函数
- 角度 UI 路由器 - 在没有参数的情况下从一个状态转换到同一状态失败
- 默认情况下,Jquery UI 模式(弹出框)控件大小和隐藏
- 如何使用 i18next 本地化属性(对于 jQuery UI 工具提示,在我的情况下使用标题)
- jQuery UI-在没有鼠标干预的情况下将Resizable()动画应用于块元素
- 在没有ui导航的情况下获取$stateParams
- 我可以在不隐藏容器的情况下使用jQuery UI幻灯片效果吗
- $.ajax在不挂起UI的情况下等待完成
- 如何在不需要刷新的情况下将Kendo UI数据向导集成到页面上
- CakePhp2自动完成(jquery-ui-folding)在没有ajax的情况下无法工作,只能使用可用的输入数组