找回密码
 立即注册

QQ登录

只需一步,快速开始

Clark.Pan 讲师达人认证 悬赏达人认证 SpreadJS 开发认证

超级版主

200

主题

9899

帖子

1万

积分

超级版主

Rank: 8Rank: 8

积分
15531

讲师达人悬赏达人微信认证勋章SpreadJS 认证SpreadJS 高级认证元老葡萄

Clark.Pan 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2020-5-25 01:38  /   查看:5483  /  回复:4
本帖最后由 ClarkPan 于 2020-5-25 01:50 编辑

背景:       SpreadJS的数据绑定功能在数据填报场景中是最常用的功能,可以很方便的将数据绑定在工作表的指定位置上。在纯数据的表格中,会给使用带来很大的遍历。由于Excel电子表格的特殊性,往往实际应用场景中经常会遇到数据的某个字段是公式,而不是计算的结果。但SpreadJS源生并不支持公式的绑定,对于这部分数据用户往往束手无策。本教程讲述通过代码对SpreadJS的数据绑定逻辑做一些改进,已达到支持数据绑定的效果并且无需修改源码,仅仅是在SpreadJS的绑定逻辑上做扩展就可以达到支持公式绑定的功能。
思路:
        在设置绑定关系的时候单独对公式进行处理,并将公式的绑定设置以tag的形式存在表格的起始单元格上。
  1. function bindingPathEnhancement(tableStartRow,tableStartColumn,bindingPathSchema){
  2.   var tableColumns = [];
  3.   var bindingPath = bindingPathSchema.bindingPath;
  4.   var properties = bindingPathSchema.properties;
  5.   //用tag记录公式列
  6.   var tag = {};
  7.   var formulaCoulumns = []
  8.   tag.bindingPath = bindingPath;
  9.   var table = sheet.tables.add('tableRecords', tableStartRow, tableStartColumn, 2, properties.length);
  10.   table.autoGenerateColumns(false);
  11.   for(var i=0;i<properties.length;i++){
  12.     var tableColumn = new GC.Spread.Sheets.Tables.TableColumn();
  13.     if(!properties[i].isFormula){
  14.       tableColumn.name(properties[i].displayName);
  15.       tableColumn.dataField(properties[i].dataField);
  16.       tableColumns.push(tableColumn);
  17.     }else{
  18.       tableColumn.name(null);
  19.       tableColumn.dataField(null);
  20.       tableColumns.push(tableColumn);
  21.       var formulaColumn = {}
  22.       formulaColumn.index = i;
  23.       formulaColumn.displayName = properties[i].displayName;
  24.       formulaColumn.dataField = properties[i].dataField;
  25.       formulaCoulumns.push(formulaColumn);
  26.     }
  27.   }
  28.   tag.formulaCoulumns = formulaCoulumns;
  29.   sheet.setTag(tableStartRow,tableStartColumn,tag);
  30.   table.bindColumns(tableColumns);
  31.   table.bindingPath(bindingPath);
  32. }
复制代码

在绑定数据时,读取tag,然后将公式在SpreadJ数据绑定完成之后单独设置。
  1. spread.suspendPaint();
  2.   spread.suspendCalcService();
  3.   source = new GC.Spread.Sheets.Bindings.CellBindingSource(dataSource);
  4.   sheet.setDataSource(source);
  5.   var tables = sheet.tables.all();
  6.   for(var i=0;i<tables.length;i++){
  7.   var tableTag = sheet.getTag(tables[i].startRow(),tables[i].startColumn());
  8.   if(tableTag){
  9.     if(tableTag.bindingPath && tableTag.formulaCoulumns){
  10.       var bindingPath = tableTag.bindingPath;
  11.       var tableSource = dataSource[bindingPath];
  12.       for(var j=0;j<tableTag.formulaCoulumns.length;j++){
  13.         var dataField = tableTag.formulaCoulumns[j].dataField;
  14.         var displayName = tableTag.formulaCoulumns[j].displayName;
  15.         var index = tableTag.formulaCoulumns[j].index;
  16.         sheet.setValue(tables[i].startRow(),tables[i].startColumn()+index,displayName);
  17.         for(var k=0;k<tableSource.length;k++){
  18.           sheet.setFormula(tables[i].startRow()+1+k,tables[i].startColumn()+index,tableSource[k][dataField]);
  19.         }
  20.       }
  21.     }
  22.   }
  23.                         }
  24.                         spread.resumeCalcService();
  25.                         spread.resumePaint();
复制代码

之后为了支持双向绑定,监听CellChanged事件,在数据源中实时修改结果。      
  1. sheet.bind(GC.Spread.Sheets.Events.CellChanged, function (e, info) {
  2.   if(info.propertyName == "formula"){
  3.     var table = sheet.tables.find(info.row,info.col);
  4.     var tableTag = sheet.getTag(table.startRow(),table.startColumn());
  5.     if(table && sheet.getTag(table.startRow(),table.startColumn())){
  6.       var bindingPath = tableTag.bindingPath;
  7.       var tableSource = dataSource[bindingPath];
  8.       var index = info.col-table.startColumn();
  9.       if(tableTag.formulaCoulumns){
  10.         for(var i=0;i<tableTag.formulaCoulumns.length;i++){
  11.           if(index == tableTag.formulaCoulumns[i].index){
  12.             var dataField = tableTag.formulaCoulumns[i].dataField;
  13.             tableSource[info.row-1-table.startRow()][dataField] = "="+ info.newValue;
  14.             break;
  15.           }
  16.         }        
  17.       }
  18.                                                 
  19.     }
  20.   }
  21.                         });
复制代码

完整demo详见附件

运行后效果如下:

点击setBindingPath加载一个带有数据与公式绑定的表格
image.png68098448.png
之后点击setDataSource给这个表格加载数据源
image.png791594848.png
加载之后结果如下:
image.png729810485.png
之后我们可以试试双向绑定的功能(修改数据和公式,下图更改了H8的值与J7的公式):
image.png896401672.png
点击getDataSource看一下效果,公式与值的改变都被记录下来
image.png284449462.png




bindFormula.html

7.31 KB, 下载次数: 143

4 个回复

倒序浏览
尼古拉斯
注册会员   /  发表于:2022-3-25 15:33:40
沙发
可以附件放个完整demo嘛
回复 使用道具 举报
Clark.Pan讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2022-3-25 15:37:48
板凳
附件就是完整demo
回复 使用道具 举报
尼古拉斯
注册会员   /  发表于:2022-3-25 15:42:09
地板

哦哦看到了,刚只看见了图片截图,多谢
回复 使用道具 举报
Lynn.Dou讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2022-3-25 16:04:09
5#
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部