Clark.Pan 发表于 2020-5-25 01:38:25

表格绑定如何绑定公式

本帖最后由 ClarkPan 于 2020-5-25 01:50 编辑

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

在绑定数据时,读取tag,然后将公式在SpreadJ数据绑定完成之后单独设置。
spread.suspendPaint();
spread.suspendCalcService();
source = new GC.Spread.Sheets.Bindings.CellBindingSource(dataSource);
sheet.setDataSource(source);
var tables = sheet.tables.all();
for(var i=0;i<tables.length;i++){
var tableTag = sheet.getTag(tables.startRow(),tables.startColumn());
if(tableTag){
    if(tableTag.bindingPath && tableTag.formulaCoulumns){
      var bindingPath = tableTag.bindingPath;
      var tableSource = dataSource;
      for(var j=0;j<tableTag.formulaCoulumns.length;j++){
      var dataField = tableTag.formulaCoulumns.dataField;
      var displayName = tableTag.formulaCoulumns.displayName;
      var index = tableTag.formulaCoulumns.index;
      sheet.setValue(tables.startRow(),tables.startColumn()+index,displayName);
      for(var k=0;k<tableSource.length;k++){
          sheet.setFormula(tables.startRow()+1+k,tables.startColumn()+index,tableSource);
      }
      }
    }
}
                        }
                        spread.resumeCalcService();
                        spread.resumePaint();
之后为了支持双向绑定,监听CellChanged事件,在数据源中实时修改结果。      
sheet.bind(GC.Spread.Sheets.Events.CellChanged, function (e, info) {
if(info.propertyName == "formula"){
    var table = sheet.tables.find(info.row,info.col);
    var tableTag = sheet.getTag(table.startRow(),table.startColumn());
    if(table && sheet.getTag(table.startRow(),table.startColumn())){
      var bindingPath = tableTag.bindingPath;
      var tableSource = dataSource;
      var index = info.col-table.startColumn();
      if(tableTag.formulaCoulumns){
      for(var i=0;i<tableTag.formulaCoulumns.length;i++){
          if(index == tableTag.formulaCoulumns.index){
            var dataField = tableTag.formulaCoulumns.dataField;
            tableSource = "="+ info.newValue;
            break;
          }
      }      
      }
                                                
    }
}
                        });
完整demo详见附件

运行后效果如下:

点击setBindingPath加载一个带有数据与公式绑定的表格

之后点击setDataSource给这个表格加载数据源

加载之后结果如下:

之后我们可以试试双向绑定的功能(修改数据和公式,下图更改了H8的值与J7的公式):

点击getDataSource看一下效果,公式与值的改变都被记录下来





尼古拉斯 发表于 2022-3-25 15:33:40

可以附件放个完整demo嘛

Clark.Pan 发表于 2022-3-25 15:37:48

附件就是完整demo

尼古拉斯 发表于 2022-3-25 15:42:09

Clark.Pan 发表于 2022-3-25 15:37
附件就是完整demo

哦哦看到了,刚只看见了图片截图,多谢

Lynn.Dou 发表于 2022-3-25 16:04:09

:mj72:
页: [1]
查看完整版本: 表格绑定如何绑定公式