本帖最后由 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[i].isFormula){
- tableColumn.name(properties[i].displayName);
- tableColumn.dataField(properties[i].dataField);
- tableColumns.push(tableColumn);
- }else{
- tableColumn.name(null);
- tableColumn.dataField(null);
- tableColumns.push(tableColumn);
- var formulaColumn = {}
- formulaColumn.index = i;
- formulaColumn.displayName = properties[i].displayName;
- formulaColumn.dataField = properties[i].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[i].startRow(),tables[i].startColumn());
- if(tableTag){
- if(tableTag.bindingPath && tableTag.formulaCoulumns){
- var bindingPath = tableTag.bindingPath;
- var tableSource = dataSource[bindingPath];
- for(var j=0;j<tableTag.formulaCoulumns.length;j++){
- var dataField = tableTag.formulaCoulumns[j].dataField;
- var displayName = tableTag.formulaCoulumns[j].displayName;
- var index = tableTag.formulaCoulumns[j].index;
- sheet.setValue(tables[i].startRow(),tables[i].startColumn()+index,displayName);
- for(var k=0;k<tableSource.length;k++){
- sheet.setFormula(tables[i].startRow()+1+k,tables[i].startColumn()+index,tableSource[k][dataField]);
- }
- }
- }
- }
- }
- 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[bindingPath];
- var index = info.col-table.startColumn();
- if(tableTag.formulaCoulumns){
- for(var i=0;i<tableTag.formulaCoulumns.length;i++){
- if(index == tableTag.formulaCoulumns[i].index){
- var dataField = tableTag.formulaCoulumns[i].dataField;
- tableSource[info.row-1-table.startRow()][dataField] = "="+ info.newValue;
- break;
- }
- }
- }
-
- }
- }
- });
复制代码
完整demo详见附件
运行后效果如下:
点击setBindingPath加载一个带有数据与公式绑定的表格
之后点击setDataSource给这个表格加载数据源
加载之后结果如下:
之后我们可以试试双向绑定的功能(修改数据和公式,下图更改了H8的值与J7的公式):
点击getDataSource看一下效果,公式与值的改变都被记录下来
|
|