SpreadJS 的 Table手动新增数据后获取完整字段的方法
问题背景
在 SpreadJS 表格控件中,当Table数据绑定后,对Table插入行,新行内填充部分单元格。在getDataSource()返回值中,关于新增行的数据对象,仅有被填充单元格对应的字段。如何获取完整字段,不论对应单元格是否填充了数据。
数据绑定使用的数据是一个JavaScript对象,在代码运行期间,这个对象被创建后即存在于内存中。这也是为什么把文件导出时虽然携带了绑定的数据源,但是导入至新应用的Workbook中再调用Worksheet:getDataSource()得到的结果为null的原因。即在新应用运行时的内存空间中没有原本的数据源对象。
解决方法
回到问题背景,虽然新增行在Table区域内,但是没有数据,意味着这行数据在数据源对象中是一个各字段属性均不存在的空对象,如图1所示。 (图1. 新行对应空数据对象)
紧接着,如果对新增行内的个别单元格写入数据,数据绑定功能的双向绑定特性将单元格值和相关字段对应起来,组成一个对象。对于没被填充数据的单元格,不做类似处理。因此,Worksheet:getDataSource()获取到新增行中的数据对象仅包含被填充单元格对应的字段属性,如图2所示。 (图2. 新行数据对象包含被填充字段属性)
那如何获取完整字段呢?即,无论填充了哪些字段,都能获取到这一行对应的完整字段。Worksheet:getDataSource()应该是做不到了,因为接口并未提供可回调操作的参数,所以需要在接口外想办法了。
回顾下对Table执行数据绑定的准备工作,对Table列设置绑定路径,而每个列的绑定路径实际上对应为数据源中的一个字段,也就是说数据源模型可知。那么,在代码上下文中存储数据源模型为元数据,同时为每个字段设置数据类型和默认值,后面会用到。如图3所示,这个元数据定义了数据源对象的各个字段,名称分别为a、b、c、d、e和f,为简单起见,定义类型均为string,且默认值为空字符串。
(图3. 数据源模型元数据)
在Worksheet:getDataSource()后,结合数据源模型元数据遍历每行单元格对应的数据对象,检查当前数据对象中是否包含元数据中的每项字段。对于未包含的字段项,在当前数据对象中扩充,并且根据元数据中该字段项的数据类型和默认值设置其值,如图4所示代码片段。由于数据源对象存在于内存空间中,因此这一修改动作会直接影响数据源对象状态。
(图4. 数据对象默认值设置代码)
最终效果如下图所示:
附上Html:
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>获取数据源全字段</title> <meta name="spreadjs culture" content="zh-cn"/> <link href="http://cdn.grapecity.com/spreadjs/hosted/css/gc.spread.sheets.excel2013white.18.1.3.css" rel="stylesheet" type="text/css"/> <link href="http://cdn.grapecity.com/spreadjs/hosted/css/gc.spread.sheets.designer.18.1.3.min.css" rel="stylesheet" type="text/css"/> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/gc.spread.sheets.all.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.shapes.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.charts.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.slicers.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.print.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.barcode.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.pdf.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.pivot.pivottables.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.tablesheet.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.ganttesheet.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.report.reportsheet.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.formulapanel.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/plugins/gc.spread.sheets.io.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/interop/gc.spread.excelio.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/resources/zh/gc.spread.sheets.resources.zh.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/gc.spread.sheets.designer.resource.cn.18.1.3.min.js"></script> <script src="http://cdn.grapecity.com/spreadjs/hosted/scripts/gc.spread.sheets.designer.all.18.1.3.min.js"></script> <style> .sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; margin: 0; top: 0; bottom: 0; left: 0; right: 0; } .gc-across-sheet-ftb { z-index: -1 !important; } .gc-across-sheet-func-popup { z-index: -1 !important; } </style> </head> <body> <!-- <button id="readyBtn">绑定事件</button> --> <button id="bindingBtn">绑定数据</button> <button id="copyToBtn">插入sheet行</button> <button id="getDataSourceBtn">获取数据源</button> <div class="sample-tutorial"> <div class="demo-options"> <div class="option-row"> <div id="formulaBar" contenteditable="true" spellcheck="false" style="font-family: Calibri;border: 1px solid #808080;width:100%;box-sizing: border-box;"></div> </div> </div> <div id="ss" style="width:100%; height: calc(100% - 20px)"></div> </div> </body> <script> window.onload = function () { var designer = new GC.Spread.Sheets.Designer.Designer(document.getElementById('ss')); var spread = designer.getWorkbook(); init(spread); } function init(spread) { var sheet = spread.getActiveSheet(); var table = sheet.tables.add('table1', 0, 0, 7, 6); document.getElementById('bindingBtn').addEventListener('click', function() { tableBinding(spread.getActiveSheet()); }); document.getElementById('getDataSourceBtn').addEventListener('click', function() { var dataSource = spread.getActiveSheet().getDataSource(); console.log('dataSource: ', dataSource); var metaData = { 'a': {type: 'string', defaultValue: ''}, 'b': {type: 'string', defaultValue: ''}, 'c': {type: 'string', defaultValue: ''}, 'd': {type: 'string', defaultValue: ''}, 'd': {type: 'string', defaultValue: ''}, 'f': {type: 'string', defaultValue: ''} }; setDefaultValues(dataSource.rT.tableData, metaData); console.log('after data process: ', dataSource); }); document.getElementById('copyToBtn').addEventListener('click', function() { var sheet = spread.getActiveSheet(); var selection = sheet.getSelections()[0]; console.log('selection: ', selection); sheet.addRows(selection.row, 1); sheet.copyTo(selection.row - 1, 1, selection.row, 1, 1, 6, GC.Spread.Sheets.CopyToOptions.span); }); } /** * 数据对象属性默认值设置 */ function setDefaultValues(objArray, metaData) { if (objArray) { objArray.forEach(obj => { for (const key in metaData) { if (metaData.hasOwnProperty(key)) { const {defaultValue} = metaData[key]; if (!obj.hasOwnProperty(key) || obj[key] == undefined) { obj[key] = defaultValue; } } } }); } return objArray; } function tableBinding(sheet) { var table = sheet.tables.all()[0]; var tableColmn1 = new GC.Spread.Sheets.Tables.TableColumn(); tableColmn1.dataField('a'); tableColmn1.name('a字段'); var tableColmn2 = new GC.Spread.Sheets.Tables.TableColumn(); tableColmn2.dataField('c '); tableColmn2.name('b字段'); var tableColmn3 = new GC.Spread.Sheets.Tables.TableColumn(); tableColmn3.dataField('b'); tableColmn3.name('c字段'); var tableColmn4 = new GC.Spread.Sheets.Tables.TableColumn(); tableColmn4.dataField('d'); tableColmn4.name('d字段'); var tableColmn5 = new GC.Spread.Sheets.Tables.TableColumn(); tableColmn5.dataField('e'); tableColmn5.name('e字段'); var tableColmn6 = new GC.Spread.Sheets.Tables.TableColumn(); tableColmn6.dataField('f'); tableColmn6.name('f字段'); table.bindColumns([tableColmn1, tableColmn2, tableColmn3, tableColmn4, tableColmn5, tableColmn6]); table.bindingPath('tableData'); table.expandBoundRows(true); var data = { 'tableData': [ { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6 }, { 'a': 2, 'b': 3, 'c': 4, 'd': 5, 'e': 6, 'f': 7 }, { 'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 7, 'f': 8 }, { 'a': 4, 'b': 5, 'c': 6, 'd': 7, 'e': 8, 'f': 9 }, { 'a': 5, 'b': 6, 'c': 7, 'd': 8, 'e': 9, 'f': 10 }, { 'a': 6, 'b': 7, 'c': 8, 'd': 9, 'e': 10, 'f': 11 }, ] }; var dataSource = new GC.Spread.Sheets.Bindings.CellBindingSource(data); sheet.setDataSource(dataSource); } </script> </html>

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Claude Code:AI编程的深度体验与实践
前言:从代码补全到智能协作的进化 在AI技术日新月异的今天,开发者们正经历着一场前所未有的效率革命。面对日益复杂的开发需求和快速迭代的技术栈,借助AI工具提升开发效率已不再是选择题,而是必选项。 我的AI编程之旅始于GitHub Copilot的早期版本。记得当时虽然惊艳于它"自动补全"的能力,但受限于上下文理解深度和代码质量,实际应用中常常是"有点作用,但不多"。随后出现的Cursor、Warp等新一代AI编程工具虽然引起了我的关注,却因种种原因未能深入体验。 直到最近尝试Claude Code,才真正体会到AI编程助手的巨大潜力。它不仅能够精准理解开发意图,更能提供符合工程规范的高质量代码建议,甚至在算法优化、代码重构等方面展现出令人惊喜的专业性。这种体验上的质变,让我意识到AI编程工具已经从简单的"代码补全"进化到了真正的"智能协作"阶段。 本文将分享我在实际开发中使用Claude Code的深度体验,包括其核心优势、适用场景以及使用技巧,希望能为同样关注AI编程工具发展的开发者提供有价值的参考。 什么是Claude Code Claude Code是Anthropic推出的本地...
- 下一篇
在 SpreadJS 中实现工作表导航:从数据获取到交互设计
前言 Microsoft Excel工作表导航功能能够提取工作簿内每个工作表中的表格(Table)、数据透视表(PivotTable)、图表(Chart)、图片、形状(Shape)等元素,并将其摘要信息以树的形式罗列显示,当点击某元素信息时,工作簿跳转至该元素所在工作表,并聚焦在该元素上,如图1所示。 (图1. Excel 工作表导航) 那么SpreadJS是否支持自定义开发实现该功能呢?撰写本文的目的正是为了介绍在SpreadJS中如何利用现有功能或产品设计自定义开发实现该功能,因此答案显然是"支持"。接下来,我们一起走进工作表导航自定义实现方案。 我们来分析下工作表导航功能的要素,参考Microsoft Excel官网对该功能的介绍,包含以下需求项: 罗列工作簿内每个工作表中的元素。 点击某元素可以跳转至相关工作表并聚焦该元素。 导航面板支持模糊搜索匹配工作表元素。 首先,需要确定SpreadJS是否能够获取工作表中的上述元素信息。SpreadJS对上述元素均抽象了独立的管理器,比如TableManager管理Table实例,PivotTableManager管理PivotTabl...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Red5直播服务器,属于Java语言的直播服务器
- CentOS关闭SELinux安全模块
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题