我使用了Handsontable(see it on GitHub)的RuleJS插件,它对基本公式很有用,但似乎缺乏递归解析。
我已经制作了一个包含两个详细示例的代码段,请查看:
$(document).ready(function () {
var container1 = $('#example1');
var container2 = $('#example2');
container1.handsontable({
data: [[1, '=A2'], ['=B2', '=5 * 2']],
colHeaders: true,
rowHeaders: true,
formulas: true,
minSpareRows: 1
});
container2.handsontable({
data: [[1, '=A2', 3], ['=C1 * B2', '=5 + 1', 3]],
colHeaders: true,
rowHeaders: true,
formulas: true,
minSpareRows: 1
});
});

<!DOCTYPE html>
<html>
<head>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/jquery/jquery-1.10.2.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.full.js"></script>
<link rel="stylesheet" media="screen" href="http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.full.css">
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/lodash/lodash.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/underscore.string/underscore.string.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/moment/moment.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/numeral/numeral.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/numericjs/numeric.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/js-md5/md5.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/jstat/jstat.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/formulajs/formula.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/js/parser.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/js/ruleJS.js"></script>
<script src="http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.formula.js"></script>
<link rel="stylesheet" media="screen" href="http://handsontable.github.io/handsontable-ruleJS/css/samples.css">
<style type="text/css">
body {background: white; margin: 20px;}
h2 {margin: 20px 0;}
</style>
</head>
<body>
<h2>Bugs in handsontable-ruleJS</h2>
<p>Both cases seem to come from the same problem, but they both worth seeing.</p>
<p>Here B1 displays the value of B2 <b>before</b> its interpretation where it should display "<b>10</b>". Just like it misses some recursive processing. Focusing the cell will show its real value "<b>=A2</b>" which will next be interpreted correctly.</p>
<div id="example1" class="handsontable"></div>
<p>This one is interesting, because when the cell "<b>A2</b>" tries to calculate "<b>C1 * B2</b>" it does "<b>3 * =5 + 1"</b> instead of "<b>3 * 6</b>", which obviously fails.</p>
<div id="example2" class="handsontable"></div>
<p>The only way to correct it is to edit "<b>C1</b>" (even without changing its value).</p>
</body>
</html>
&#13;
如果您更喜欢JSFiddle,here you go。
最好的问候。
修改:使用嵌入代码段并进入全屏时,您可能看不到第一个错误,因为它似乎触发了表的刷新。使用JSFiddle可以获得更好的结果。
编辑2(求助):好的,我想我已修补了它,you can find the result here。当Stackoverflow允许我这样做时,我会发布一个完整的答案。任何反馈仍然是受欢迎的,我确信有更好的方法可以做到这一点,但至少它现在似乎有效。
答案 0 :(得分:1)
可在此处找到工作代码:http://jsfiddle.net/71o23gp0/8/。
重要的是取代:
var custom = {
cellValue: instance.getDataAtCell
};
通过
var custom = {
cellValue: function(row, col){
var value = instance.getDataAtCell(row, col);
if (value && value[0] === '=') {
var formula = value.substr(1).toUpperCase();
var cellId = instance.plugin.utils.translateCellCoords({
row: row,
col: col
});
var item = instance.plugin.matrix.getItem(cellId);
if (!item) {
item = instance.plugin.matrix.addItem({
id: cellId,
formula: formula
});
} else {
item = instance.plugin.matrix.updateItem({
id: cellId,
formula: formula
});
}
var formulaResult = instance.plugin.parse(formula, {
row: row,
col: col,
id: cellId
});
value = formulaResult.result || '#ERROR';
formulasResults[cellId] = value;
instance.plugin.matrix.updateItem(item, {
formula: formula,
value: formulaResult.result,
error: formulaResult.error
});
}
return value;
}
};
它不是简单地返回单元格的值,而是检查它是否为公式,如果是,则解析它。因为在解析公式时,RuleJS会调用此方法,所以这会使分辨率递归。然后缓存结果以获得更好的性能。
源代码中还有其他一些小修改,但我在每次修改之前和之后都在小提琴中添加了注释。
答案 1 :(得分:0)
在这个问题的答案https://stackoverflow.com/a/35528447/489865之后,我进一步修补了一下。工作代码可以在http://jsfiddle.net/ufL1vts5/找到。
重要的变化是存储在formulasResults[]
而不只是&#34;结果&#34;而是由instance.plugin.parse()
返回的整个对象,以便按照以下方式拾取公式的单元格突出显示:
// parse formula
var newValue = instance.plugin.parse(formula, {row: row, col: col, id: cellId});
// cache result
formulasResults[cellId] = newValue;
我的修改包括:
将整个instance.plugin.parse()
对象存储在formulasResults[]
中,
以便应用formula
/ formula-error
CSS样式。 [注意
这不是完美的:它会选择&#34;计算&#34;配方风格
正确,但有时应该只有formula-error
样式
得到formula
风格---但足以满足我的需要。]
添加了formula
&amp; formula-error
CSS样式(来自提供
handsontable.formula.css
)进入JSFiddle示例,以便那个单元格
可以看到突出显示。
增加了2个额外的例子:一个来自 handsontable formula returning #NEED_UPDATE, 显示它也有效,并且提供的示例中有一个 handsontable-ruleJS 位于https://github.com/handsontable/handsontable-ruleJS/blob/master/index.html。
删除了新添加的beforeRender
挂钩
instance.removeHook('beforeRender', beforeRender);
中的this.init = function ()
。
更改了handsontable.formula.js
中的一些代码布局,以便它
最小化与提供的差异
的 handsontable-ruleJS 强>