Handsontable RuleJS缺少递归解析 [英] Handsontable RuleJS missing recursive resolution

查看:842
本文介绍了Handsontable RuleJS缺少递归解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用RuleJS插件Handsontable(看到它在GitHub上),这对于基本公式的伟大工程但似乎缺乏递归解析。

我做了一个包含两个具体例子code片段,请检查一下:

\r
\r

$(文件)。就绪(函数(){\r
  VAR container1 = $('#例1');\r
  VAR container2的= $('#例2');\r
  \r
  container1.handsontable({\r
    数据:[[1,'= A'],['= B2','= 5 * 2'],\r
    colHeaders:真实,\r
    rowHeaders:真实,\r
    公式:真实,\r
    minSpareRows:1\r
  });\r
  \r
  container2.handsontable({\r
    数据:[[1,'= A 2',3],['= C1 * B2','= 5 + 1',3]]\r
    colHeaders:真实,\r
    rowHeaders:真实,\r
    公式:真实,\r
    minSpareRows:1\r
  });\r
});

\r

<!DOCTYPE HTML>\r
< HTML和GT;\r
< HEAD>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/jquery/jquery-1.10.2.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.full.js\"></script>\r
    &LT;链接rel =stylesheet属性的媒体=屏幕上的href =htt​​p://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.full.css&GT;\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/lodash/lodash.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/underscore.string/underscore.string.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/moment/moment.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/numeral/numeral.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/numericjs/numeric.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/js-md5/md5.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/jstat/jstat.js\"></script>\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/lib/formulajs/formula.js\"></script>\r
    &所述; SCRIPT SRC =htt​​p://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/js/parser.js&GT;&下; /脚本&GT;\r
    &所述; SCRIPT SRC =htt​​p://handsontable.github.io/handsontable-ruleJS/lib/RuleJS/js/ruleJS.js&GT;&下; /脚本&GT;\r
    &LT;脚本src=\"http://handsontable.github.io/handsontable-ruleJS/lib/handsontable/handsontable.formula.js\"></script>\r
    &LT;链接rel =stylesheet属性的媒体=屏幕上的href =htt​​p://handsontable.github.io/handsontable-ruleJS/css/samples.css&GT;\r
\r
    &LT;风格类型=文/ CSS&GT;\r
        身体{背景:白色;保证金:20像素;}\r
        H2 {保证金:为20px 0;}\r
    &LT; /风格&GT;\r
&LT; /头&GT;\r
&LT;身体GT;\r
  &LT; H2&GT;错误在handsontable-ruleJS&LT; / H&GT;\r
\r
  &LT; P&GT;这两种情况似乎都来自相同的问题,但他们都有看头&LT; / P&GT;\r
  &LT; P&gt;此处B1显示B2&LT的价值; B&GT;与前LT; / B&GT;其除pretation它应该显示&LT; B&GT; 10&LT; / B&gt;中。就像它错过了一些递归处理。聚焦单元将展示其真正的价值&LT; B&GT; = A2&LT; / B&gt;中这将是下一个正确PTED间$ P $&LT; / P&GT;\r
  &LT; D​​IV ID =例1级=handsontable&GT;&LT; / DIV&GT;\r
\r
  &LT; P&gt;这一个是有趣,因为当细胞&LT; B&GT; A2&LT; / B&gt;中尝试计算&LT; B&GT; C1 * B2&LT; / B&gt;中它&所述b取代; 3 * = 5 + 1&下; / B个代替&所述b取代; 3 * 6≤/ B&gt;中,这显然失败&下; / P&GT;\r
  &LT; D​​IV ID =例2级=handsontable&GT;&LT; / DIV&GT;\r
  &LT; P&gt;到更正的唯一方法是编辑&LT; B&GT; C1&LT; / B&gt;中(即使不改变其值)LT; / P&GT;\r
&LT; /身体GT;\r
&LT; / HTML&GT;\r
  

\r

\r
\r

如果您preFER的jsfiddle,在这里你去

最好的问候。

修改:使用嵌入片段,并要全屏,因为它似乎触发表的刷新时,您可能不会看到的第一个错误。使用的jsfiddle获得更好的结果。

编辑2(解决):好吧,我想我已经修补它,你可以在这里找到的结果。我会发布一个完整的答案时,#1让我这样做。任何反馈仍然是欢迎的,我敢肯定有一个更好的办法来做到这一点,但至少现在看来工作。


解决方案

工作code可以在这里找到:的 http://jsfiddle.net/71o23gp0/8/

最重要的部分是替换:

  VAR定制= {
      cellValue:instance.getDataAtCell
};

通过

  VAR定制= {
        cellValue:函数(行,列){
          VAR值= instance.getDataAtCell(行,列);
          如果(价值和放大器;&放大器;值[0] ==='='){
              VAR公式= value.substr(1).toUpperCase();
              VAR CELLID = instance.plugin.utils.translateCellCoords({
                  行:行,
                  西:COL
              });
              VAR项目= instance.plugin.matrix.getItem(CELLID);              如果(!项){
                  项目= instance.plugin.matrix.addItem({
                      ID:CELLID,
                      配方:配方
                  });
              }其他{
                  项目= instance.plugin.matrix.updateItem({
                      ID:CELLID,
                      配方:配方
                  });
              }
              VAR formulaResult = instance.plugin.parse(公式,{
                  行:行,
                  西:关口,
                  ID:CELLID
              });
              值= formulaResult.result || '#错误';
              formulasResults [CELLID] =价值;
              instance.plugin.matrix.updateItem(项目,{
                  配方:配方,
                  值:formulaResult.result,
                  错误:formulaResult.error
              });
          }
          返回值;
      }
    };

而不是简单地返回单元格的值,它会检查,如果它是一个公式,如果是这样解决。由于这种方法是通过RuleJS解析公式时调用,这使分辨率递归。然后将结果缓存提高性能。

有源$ C ​​$ C等细微的修改,但是我之前每修改后已经添加了小提琴的意见。

I use RuleJS plugin for Handsontable (see it on GitHub) which works great for basic formulas but seems to lack recursive resolution.

I've made a code snippet containing two detailed examples, please check it out :

$(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>
  

If you prefer JSFiddle, here you go.

Best regards.

Edit: You may not see the first bug when using the embed snippet and going to fullscreen because it seems to trigger a refresh of the table. Use the JSFiddle for better results.

Edit 2 (SOLVED): Ok I think I've patched it, you can find the result here. I'll post a complete answer when Stackoverflow allows me to do it. Any feedback is still welcome, I'm sure there is a better way to do it but at least it seems to work now.

解决方案

The working code can be found here : http://jsfiddle.net/71o23gp0/8/.

The important part was to replace :

var custom = {
      cellValue: instance.getDataAtCell
};

By

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;
      }
    };

Instead of simply returning the value of the cell, it checks if it's a formula and resolve it if so. Because this method is called by RuleJS when resolving a formula, this make the resolution recursive. The result is then cached for better performance.

There are other minor modifications in the source code, but I've added comments in the fiddle before and after every modification.

这篇关于Handsontable RuleJS缺少递归解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆