找回密码
 立即注册

QQ登录

只需一步,快速开始

lihuiqian1991

初级会员

16

主题

35

帖子

450

积分

初级会员

积分
450
lihuiqian1991
初级会员   /  发表于:2018-4-2 13:35  /   查看:4567  /  回复:9
本帖最后由 lihuiqian1991 于 2018-4-13 11:12 编辑

SpreadJS版本:11.0.0
需求:
1. 在表格中,当用户没有输入内容时,单元格为黄色;
2. 用户输入内容后,单元格变为白色;
3. 用户删除内容后,单元格变为黄色。
4. 输入方式:①编辑单元格;②复制粘贴;③拖放单元格;④拖拽单元格右下角的手柄;
5. 删除方式:①编辑单元格,删除其中的内容;②使用Delete键;③通过复制粘贴、拖放、拖拽其他空白单元格;

问题(示例代码见最后):
1. 通过编辑单元格的方式删除A1中的内容,A1单元格未变黄;
    对比:通过使用Delete键删除B1中的内容,B1单元格变黄;
2. 使用Delete键删除A2,B2单元格中的内容,使其变黄;
    通过编辑单元格的方式给A2填写内容,A2单元格仍为黄色,再次编辑A2,修改其中的内容,A2单元格变为白色;
    对比:复制C2单元格的内容,粘贴到B2单元格中,B2单元格变为白色;

分析:
1. 触发CellChanged事件,会产生问题;
2. 触发RangeChanged事件,不会产生问题;
3. 产生问题发生在单元格由空变为有值、或由有值变为空的时候;
4. Debug发现,发生问题时,会由SpreadJS自动触发一次CellChanged事件,设置单元格格式;
5. Debug发现,4.中触发事件的原因可能与AutoFormat有关。

麻烦给出修复或者通过代码绕过上述问题,谢谢。

代码:
借用页面:http://demo.gcpowertools.com.cn/ ... /demos/spreadEvents
替换JavaScript:

  1.     $(document).ready(function () {
  2.         var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 3 });
  3.         initSpread(spread);
  4.     });

  5.     function initSpread(spread) {
  6.         var spreadNS = GC.Spread.Sheets;
  7.         var sd = dataSource;
  8.         var sheet = spread.getActiveSheet();
  9.         if (sd.length > 0) {
  10.             sheet.setDataSource(sd);
  11.         }
  12.         sheet.setColumnWidth(0, 160);
  13.         sheet.setColumnWidth(1, 70);
  14.         sheet.setColumnWidth(2, 90);
  15.         sheet.setColumnWidth(3, 110);
  16.         sheet.setColumnWidth(4, 80);
  17.         sheet.setColumnWidth(6, 110);

  18.         spread.bind(spreadNS.Events.CellChanged, function (e, args) {
  19.                         //spread.suspendPaint();
  20.                         //spread.suspendCalcService(false);
  21.                         //spread.suspendEvent();            
  22.                         if (args.propertyName === 'value') {
  23.                                 if (args.newValue !== undefined && args.newValue !== null) {
  24.                                         var style = new spreadNS.Style();
  25.                                         style.backColor = 'rgb(255,255,255)';
  26.                                         args.sheet.setStyle(args.row, args.col, style);
  27.                                 } else {
  28.                                         var style = new spreadNS.Style();
  29.                                         style.backColor = 'rgb(255,255,204)';
  30.                                         args.sheet.setStyle(args.row, args.col, style);
  31.                                 }
  32.                         }
  33.                         //spread.resumeEvent();
  34.                         //spread.resumeCalcService(false);
  35.                         //spread.resumePaint()
  36.         });
  37.                
  38.         spread.bind(spreadNS.Events.RangeChanged, function (e, args) {
  39.                         //spread.suspendPaint();
  40.                         //spread.suspendCalcService(false);
  41.                         //spread.suspendEvent();   
  42.             let len = args.changedCells.length;
  43.             for (let i = 0; i < len; i++) {
  44.                 let cell = args.changedCells[i];
  45.                 let value = sheet.getValue(cell.row, cell.col);
  46.                                 if (value !== undefined && value !== null) {
  47.                                         var style = new spreadNS.Style();
  48.                                         style.backColor = 'rgb(255,255,255)';
  49.                                         args.sheet.setStyle(cell.row, cell.col, style);
  50.                                 } else {
  51.                                         var style = new spreadNS.Style();
  52.                                         style.backColor = 'rgb(255,255,204)';
  53.                                         args.sheet.setStyle(cell.row, cell.col, style);
  54.                                 }
  55.                         }
  56.                         //spread.resumeEvent();
  57.                         //spread.resumeCalcService(false);
  58.                         //spread.resumePaint()
  59.         });
  60.     };
复制代码


9 个回复

倒序浏览
Clark.Pan讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2018-4-2 18:12:32
沙发
您好,这个问题正在处理中,明天将制作好的demo发给您。
回复 使用道具 举报
Clark.Pan讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2018-4-3 15:29:17
板凳
您好:

这个问题是代码执行顺序的问题,因为更改Style会触发cellchange,而当所有的cellchange全部触发完毕后才会进行repaint,所以后面触发的cellchanged内容,会将在之前设定的内容覆盖掉,导致您描述的问题,解决方法是设置setTimeOut来更改代码执行的顺序,更改后的代码在下面,您可以参考一下:
  1. $(document).ready(function () {
  2.         var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 3 });
  3.         initSpread(spread);
  4.     });

  5.     function initSpread(spread) {
  6.         var spreadNS = GC.Spread.Sheets;
  7.         var sd = dataSource;
  8.         var sheet = spread.getActiveSheet();
  9.         if (sd.length > 0) {
  10.             sheet.setDataSource(sd);
  11.         }
  12.         sheet.setColumnWidth(0, 160);
  13.         sheet.setColumnWidth(1, 70);
  14.         sheet.setColumnWidth(2, 90);
  15.         sheet.setColumnWidth(3, 110);
  16.         sheet.setColumnWidth(4, 80);
  17.         sheet.setColumnWidth(6, 110);

  18.         spread.bind(spreadNS.Events.CellChanged, function (e, args) {
  19.                         //spread.suspendPaint();
  20.                         //spread.suspendCalcService(false);
  21.                         //spread.suspendEvent();            
  22.                         if (args.propertyName === 'value') {
  23.                                 if (args.newValue !== undefined && args.newValue !== null) {
  24.                                         var style = new spreadNS.Style();
  25.                                         style.backColor = 'rgb(255,255,255)';
  26.                                                                                 setTimeout(function(){
  27.                                                                                         args.sheet.setStyle(args.row, args.col, style);
  28.                                                                                 },0);
  29.                                        
  30.                                 } else {
  31.                                         var style = new spreadNS.Style();
  32.                                         style.backColor = 'rgb(255,255,204)';
  33.                                                                                 setTimeout(function(){
  34.                                                                                          args.sheet.setStyle(args.row, args.col, style);
  35.                                                                                 },0);
  36.                                        
  37.                                 }
  38.                         }
  39.                         //spread.resumeEvent();
  40.                         //spread.resumeCalcService(false);
  41.                         //spread.resumePaint()
  42.         });
  43.                
  44.                
  45.         spread.bind(spreadNS.Events.RangeChanged, function (e, args) {
  46.                         //spread.suspendPaint();
  47.                         //spread.suspendCalcService(false);
  48.                         //spread.suspendEvent();   
  49.             let len = args.changedCells.length;
  50.             for (let i = 0; i < len; i++) {
  51.                 let cell = args.changedCells[i];
  52.                 let value = sheet.getValue(cell.row, cell.col);
  53.                                 if (value !== undefined && value !== null) {
  54.                                         var style = new spreadNS.Style();
  55.                                         style.backColor = 'rgb(255,255,255)';
  56.                                         args.sheet.setStyle(cell.row, cell.col, style);
  57.                                 } else {
  58.                                         var style = new spreadNS.Style();
  59.                                         style.backColor = 'rgb(255,255,204)';
  60.                                         args.sheet.setStyle(cell.row, cell.col, style);
  61.                                 }
  62.                         }
  63.                         //spread.resumeEvent();
  64.                         //spread.resumeCalcService(false);
  65.                         //spread.resumePaint()
  66.         });
  67.     };
复制代码
回复 使用道具 举报
lihuiqian1991
初级会员   /  发表于:2018-4-4 16:44:54
地板
ClarkPan 发表于 2018-4-3 15:29
您好:

这个问题是代码执行顺序的问题,因为更改Style会触发cellchange,而当所有的cellchange全部触发 ...

你好,后面的cellChanged内容覆盖前面的这一点我是知道的。

1. 在没有内容的单元格中输入内容,将触发3次事件,分别为:
1.1. CellChanged, Value
1.2. CellChanged, Style <- 这是代码29行设定的 // 21~23、41~43行的注释取消后将不再触发
1.3. CellChanged, Style <- 这是SpreadJS自动触发的

2. 在没有内容的单元格中粘贴进文本内容,将触发2此事件,分别为:
2.1. RangeChanged, Value
2.2. CellChanged, Style <- 这是代码52行设定的 // 48~50、65~67行的注释取消后将不再触发

我想知道,
①为什么1.会比2.多触发一次事件,因为什么设定触发了这次事件;
②能不能通过设置避免1.3事件的触发,或者在处理1.3的事件过程中,终止事件执行;

现在的项目的处理逻辑是:①. 通过CellChanged事件/RangeChanged事件的处理,统计出所有值变更的单元格;②. 调用数据处理API统一处理变更的数据,并统计出所有受影响的单元格(可能比①中统计的单元格多很多);③.在画面对所有受影响的单元格进行统一的刷新。
如果给所有刷新单元格格式的代码加上setTimeout,将对大量数据处理时的性能产生非常大的影响;如果给CellChanged事件单独的处理代码,将对现有代码产生结构性的影响。
所以希望能有一个优雅的方式解决这个问题,从源头上阻止1.3的事件产生,或者在SpreadJS自动触发1.3的事件的处理过程中阻止它继续执行下去。
回复 使用道具 举报
Clark.Pan讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2018-4-4 18:01:00
5#
1.因为formatter也是style的一个属性,第三次是因为formatter触发的。
2.您在代码的事件中写判断,让其什么都不做就行了。完全阻止是不可能的,事件只是监听,即使不监听也会走相应的机制,只是不触发事件而已
回复 使用道具 举报
lihuiqian1991
初级会员   /  发表于:2018-4-8 10:09:06
6#
ClarkPan 发表于 2018-4-4 18:01
1.因为formatter也是style的一个属性,第三次是因为formatter触发的。
2.您在代码的事件中写判断,让其什 ...

你好,可能我没有表述清楚问题。

经过我的测试,在SpreadJS中:
在单元格中输入“2%”会触发auto format,最终单元格里的内容是“2%”;
从文本编辑器中复制字符串“2%”,选中单元格,按Ctrl+V,不会触发auto format,最终单元格里的内容是“0.02”;
同样的测试,在Excel中,单元格里的内容均为“2%”。

是不是触发SpreadJS的RangeChanged事件时,遗漏了auto format?

--------------------------------------------------------------------------------------------------------------

另一个问题,经过我的黑盒测试,猜测SpreadJS的Auto Format过程:
1. 用户在单元格中输入内容
2. 拷贝当前单元格的style
3. 触发CellChanged事件,设置单元格的value = 1.中用户输入内容
4. 触发CellChanged事件,设置单元格的style = 2.中拷贝的style

上述步骤中,2.和3.交换一下是不是更合理一些,现在可以做到吗,还是说交换2.和3.会影响到其他某一些具体的功能?
回复 使用道具 举报
Clark.Pan讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2018-4-8 17:22:08
7#
这个问题是产品与Excel的一个已知差异,formatter按道理属于格式,是不能够去影响最终的值的,但是Excel中做了在百分比格式中做了特殊处理,从而使其影响到了单元格的真实值,SpreadJS这边没有这么做。
另外您追问的问题,肯定是不行的,因为事件本身是cellchanged事件,changed说明说明单元格改变已经完成之后再触发该事件,这时cell change已经完成,所以2,3不可能改变。
回复 使用道具 举报
lihuiqian1991
初级会员   /  发表于:2018-4-13 11:10:43
8#
ClarkPan 发表于 2018-4-8 17:22
这个问题是产品与Excel的一个已知差异,formatter按道理属于格式,是不能够去影响最终的值的,但是Excel中 ...

你的这个回答提醒了我,是不是还有CellChanging事件,不过没找到。希望以后SpreadJS能有更丰富的事件可供我们选择。
这个问题已经通过其他手段绕过去了,谢谢回答。
回复 使用道具 举报
lihuiqian1991
初级会员   /  发表于:2018-4-13 11:10:47
9#
ClarkPan 发表于 2018-4-8 17:22
这个问题是产品与Excel的一个已知差异,formatter按道理属于格式,是不能够去影响最终的值的,但是Excel中 ...

你的这个回答提醒了我,是不是还有CellChanging事件,不过没找到。希望以后SpreadJS能有更丰富的事件可供我们选择。
这个问题已经通过其他手段绕过去了,谢谢回答。
回复 使用道具 举报
Clark.Pan讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2018-4-13 18:29:38
10#
为什么没有cellchanging事件是这样的,cellchanged事件是因为在单元格changed之后告诉您我这边已经changed了,您可以有没有可以进行的事情要做。如果要做可以在事件中完成。
一般changing事件主要为了给用户一个可以判断撤掉的行为。而cellchanging完全可以在其触发的行为中去判断所以不需要提供。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部