找回密码
 立即注册

QQ登录

只需一步,快速开始

wangboyang

初级会员

9

主题

37

帖子

239

积分

初级会员

积分
239

微信认证勋章

wangboyang
初级会员   /  发表于:2016-5-12 15:06  /   查看:11159  /  回复:11
你好 关于Spread中的CellChange事件我做了如下实验很是不解:
事件代码如下:
  1.   //当单元格改变的时候
  2.             $("#planFormSpread").data("spread").getActiveSheet().bind(GcSpread.Sheets.Events.CellChanged, function (e, info) {
  3.                 if (info.sheetArea === GcSpread.Sheets.SheetArea.viewport) {
  4.                     /*每次改变单元格事件会出发多次*/
  5.                     //第一次:原公式 第二次:原值 第三次:新公式 第四次:新值
  6.                     alert("Cell index (" + info.row + "," + info.col + "," + sheet.getValue(info.row, info.col) + "," + sheet.getFormula(info.row, info.col) + ")");
  7.                 }
  8.             });
复制代码

第一种:普通无公式单元格,假设单元格默认为:0 修改后为:11
会弹出两次,分别为:<1>: Cell index ("1,1,0,null)  <2>:Cell index ("1,1,11,null)


第二种:有公式的单元格,,假设单元格公式为:B1+C1 默认计算结果为:0 修改后为:11
会弹出三次,分别为:<1>: Cell index ("1,1,0,B1+C1)  <2>:Cell index ("1,1,0,null) <3> Cell index ("1,1,11,null)


第三种:在第二种情况修改后再次编辑该单元格,修改值为:222
会弹出一次,为:<1>: Cell index ("1,1,0,222)


那么问题就来了,第三种情况已经把公式去掉了,就变成第一种情况的普通单元格,但是第一种情况会弹出两次分别是修改前的值和修改后的值,但是第三种情况以后无论怎么修改只会弹出一次,并且值永远是最新的。


我现在有个需求,无论单元格是否有公式,当修改后我都想把单元格的index、修改前的值,修改后的值,修改前的公式,修改后的公式都记录下来,如何做到?

11 个回复

倒序浏览
dexteryao讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2016-5-13 10:40:12
推荐
明白了,那是需要每次都保存oldvalue 和 newvalue。 您可以将 这些信息都封装起来放到cell tag里,方便使用。
回复 使用道具 举报
dexteryao讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2016-5-13 09:24:28
推荐
本帖最后由 dexteryao 于 2016-5-13 09:26 编辑

您好,首先说明一下为什么value改formula只触发一次。
CellChanged 和 ValueChanged 都是属于数据层面的事件,只有当spread 内部的Value Model 发生变化才会触发。当一个单元格有formula的时候,getValue所获取到的值是通过formula计算的,实际的valueModel可以说是没有用的,设置了公式,我们就不关心他的value了。当我们通过输入改变了formula,也只会触发formula change,因为是formula change 导致的界面显示值得变化。
举个例子 一个单元格A2有公式 “=A1”, 当我们改变了A1的内容 ,这时A2的内容也会发生变化,但实际上A2内部并没有发生任何变化,A2也不触发事件.

回到您的问题,如果想知道公式发生变化前后的计算值可以在EditStarting 先缓存下来变化前的计算值就是oldvalue,然后在获取当前值就是newValue。

  1.             var activeSheet = spread.getActiveSheet();
  2.             var cacheValue;
  3.             activeSheet.bind(GcSpread.Sheets.Events.CellChanged, function (e, info) {
  4.                 if(info.sheetArea === GcSpread.Sheets.SheetArea.viewport){
  5.                     console.log(info.propertyName);
  6.                     // console.log(info)
  7.                     switch (info.propertyName){
  8.                         case "value":
  9.                             console.log(info.oldValue, info.newValue)
  10.                             break;
  11.                         case "formula":
  12.                             if(!info.oldValue && info.newValue){ //value to formula                                
  13.                                  console.log(info.oldValue, info.newValue)
  14.                                  console.log("value")
  15.                                  console.log(cacheValue, activeSheet.getValue(info.row, info.col))
  16.                             }
  17.                             else if(info.oldValue && info.newValue){ //formula change
  18.                                  console.log(info.oldValue, info.newValue)
  19.                                  console.log("value")
  20.                                  console.log(cacheValue, activeSheet.getValue(info.row, info.col))
  21.                             }
  22.                             else{ // formula to value
  23.                                  console.log(info.oldValue, info.newValue)
  24.                             }
  25.                             break;
  26.                     }

  27.                 }
  28.             });

  29.             activeSheet.bind(GcSpread.Sheets.Events.EditStarting, function (sender, args) {
  30.                 cacheValue = activeSheet.getValue(args.row, args.col);
  31.                 //console.log(cacheValue);
  32.             })
复制代码


回复 使用道具 举报
dexteryao讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2016-5-12 17:07:05
沙发
这个事件的info还有个参数是 propertyName
第一种情况触发两次,一次是style 一次是value
第二中 情况 有style value "formula" 三次。
第三种 只有 "formula"

所以您需要在事件中判断propertyName 的类型,对于 formula 和 value,info都有 newValue和 oldValue的属性。 这样您直接记录就好了
回复 使用道具 举报
wangboyang
初级会员   /  发表于:2016-5-12 17:51:11
板凳
dexteryao 发表于 2016-5-12 17:07
这个事件的info还有个参数是 propertyName
第一种情况触发两次,一次是style 一次是value
第二中 情况  ...

可不可以针对判断propertyName 的类型,对于 formula 和 value,info都有 newValue和 oldValue的属性。
来段代码看看
回复 使用道具 举报
wangboyang
初级会员   /  发表于:2016-5-12 17:58:05
地板
dexteryao 发表于 2016-5-12 17:07
这个事件的info还有个参数是 propertyName
第一种情况触发两次,一次是style 一次是value
第二中 情况  ...

而且这个参数info里面都有什么东西,我在帮助文档里面搜什么可以看到?
回复 使用道具 举报
wangboyang
初级会员   /  发表于:2016-5-12 19:04:11
5#
dexteryao 发表于 2016-5-12 17:07
这个事件的info还有个参数是 propertyName
第一种情况触发两次,一次是style 一次是value
第二中 情况  ...

而且我又做了个测试,代码如下:
  1.   $("#planFormSpread").data("spread").getActiveSheet().bind(GcSpread.Sheets.Events.CellChanged, function (e, info) {
  2.                 if (info.sheetArea === GcSpread.Sheets.SheetArea.viewport) {
  3.                     /*放入对应的值*/
  4.                     switch (info.propertyName) {
  5.                         case "value":
  6.                             alert("value|new:" + info.newValue + "|old:" + info.oldValue);
  7.                             break;
  8.                         case "formula":
  9.                             alert("formula|new:" + info.newValue + "|old:" + info.oldValue);
  10.                             break;
  11.                     }
  12.                 }
  13.             });
复制代码

当单元格为普通的值时,将值改成公式,只会触发一次formula
结果为:formula|new:H5+6|old:null,
从结果可以看出并不会触发value,但我确实将值改成了公式,所以无法获得变为公式之前的值是多少?
PS:将公式变为值,会触发formula一次 value一次 ,正常。
回复 使用道具 举报
wangboyang
初级会员   /  发表于:2016-5-13 10:00:22
7#
dexteryao 发表于 2016-5-13 09:24
您好,首先说明一下为什么value改formula只触发一次。
CellChanged 和 ValueChanged 都是属于数据层面的事 ...

此乃正解,多谢指导。
回复 使用道具 举报
dexteryao讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2016-5-13 10:18:31
8#
多问一下,您是在什么业务背景下需要记录用户行为?
回复 使用道具 举报
wangboyang
初级会员   /  发表于:2016-5-13 10:26:57
9#
dexteryao 发表于 2016-5-13 10:18
多问一下,您是在什么业务背景下需要记录用户行为?

就是制定计划的表格,这个表格的格式可能会有些复杂,每一行的单元格只有前两个单元格是输入的,后面都是根据公式计算的,但是公式算出来的结果计划编制人员是可以修改的,比如将公式删除,该成自己输入的值,那么表单就需要将所有修改过的单元格背景变色标记出来哪些地方人为修改了,再就是当鼠标放到人为修改的单元格上,提示修改的oldvalue newvalue。
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 立即注册
返回顶部