
amis input-excel 前端 Excel 解析控件完全指南解析模式、多文件与源码级实现剖析【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis本文围绕 amis 低代码框架中的input-excel表单控件展开它通过前端直接解析.xlsx/.xls文件将表格内容转换为表单数据从而省去后端的 Excel 解析成本并支持配合input-table做二次编辑。读完本篇你将掌握该组件的全部配置项对象/二维数组解析、多 sheet、多文件、图片与富文本解析、autoFill 自动填充、事件与动作的完整用法并基于源码理解其底层解析链路exceljs xlsx 双引擎、数据格式细节与测试验证方式。组件定位为什么要前端解析 Excelinput-excel是一个表单控件isFormItem: true在 amis 中的注册见 minimal.ts其完整实现位于 InputExcel.tsx。使用它主要有两个好处节省后端开发成本文件在浏览器端就被解析成结构化数据后端只需接收普通 JSON无需再次解析 Excel前端实时预览与二次修改解析结果直接成为表单值可配合input-table等组件在提交前人工校对、修正。版本说明2.10.0 以上版本支持 xls 文件格式2.9.0 及以下版本只支持 xlsx。当前仓库amis包版本为 6.13.0见 package.json以下所有用法均适用于当前代码。基本使用默认对象数组模式默认情况下只解析第一个 sheet 的内容默认模式是把第一行作为对象里的键解析成对象数组。选择上传文件后就能知道最终会解析成什么数据{ type: form, api: /api/mock2/form/saveForm, debug: true, body: [ { type: input-excel, name: excel, label: 上传 Excel } ] }假设上传一个类似这样的 Excel 内容|名称|网址| |amis|https://baidu.gitee.io/amis| |百度|https://www.baidu.com|解析后的数据格式将会是[ { 名称: amis, 网址: https://baidu.gitee.io/amis }, { 名称: 百度, 网址: https://www.baidu.com } ]配合 input-table 实现上传后二次编辑可以配合input-table来实现在上传解析后对数据做人工修正{ type: form, api: /api/mock2/form/saveForm, body: [ { type: input-excel, name: excel, label: 上传 Excel, placeholder: 请拖拽Excel文件到当前区域 }, { type: input-table, name: excel, visibleOn: data.excel, columns: [ { name: 名称, label: 名称, type: input-text }, { name: 网址, label: 网址, type: input-text } ] } ] }使用要点必须保证input-table的name和input-excel的name一致都指向同一份解析数据excelcolumns中每一列的name需要和 Excel 的第一行列名一致这样表格里才能正确回显每列的值visibleOn: data.excel让表格在解析完成后才显示placeholder2.8.1 起支持用于自定义拖拽区的提示文本。二维数组模式parseMode: array除了默认的对象数组格式还可以用二维数组方式保留原始行列结构包含表头行方法是设置parseMode: array{ type: form, api: /api/mock2/form/saveForm, debug: true, body: [ { type: input-excel, name: excel, parseMode: array, label: 上传 Excel } ] }如果还是前面的例子解析结果将会是[ [名称, 网址], [amis, https://baidu.gitee.io/amis], [百度, https://www.baidu.com] ]两种模式在源码readWorksheet中对应不同分支array模式直接按行遍历worksheet.eachRow输出row.valuesobject模式则把第一行rowNumber 1取值作为字段名后续每行按列号映射成对象。这一实现见 InputExcel.tsx。解析多个 sheetallSheets默认配置只解析第一个可见sheet如果要解析多个 sheet可以通过allSheets: true开启此时数据会增加一个层级每个 sheet 一段带sheetName{ type: form, api: /api/mock2/form/saveForm, debug: true, body: [ { type: input-excel, name: excel, allSheets: true, label: 上传 Excel } ] }如果按之前的例子结果将会是[ { sheetName: Sheet1, data: [ { 名称: amis, 网址: https://baidu.gitee.io/amis }, { 名称: 百度, 网址: https://www.baidu.com } ] } ]从源码看隐藏 sheet 会被跳过单 sheet 模式下通过workbook.worksheets.find(sheet sheet.state ! hidden)选取第一个非隐藏工作表多 sheet 模式下parseAllSheets内遇到state hidden的 sheet 直接return见 InputExcel.tsx 与 parseAllSheets。解析多个文件multiple 与 maxLength可以配置multiple: true来开启多文件解析功能通过maxLength: 5限制最多上传 5 个文件两者均为 6.13.0 引入即当前仓库版本{ type: form, api: /api/mock2/form/saveForm, debug: true, body: [ { type: input-excel, name: excel, allSheets: true, label: 上传 Excel, multiple: true, maxLength: 5 } ] }多文件模式的行为细节均可在源码中验证单文件模式下multiple未开启每次选择文件都会替换已有文件只处理第一个文件多文件模式下则是追加并受maxLength - 已有文件数的剩余名额约束超额部分直接丢弃见 handleDrop并行解析多个文件通过Promise.all并行处理全部解析完成后一次性更新表单值见 processFiles多文件模式下的输出结构值变为数组每项包含fileName与data其中data为各 sheet 的{sheetName, data}结构开启parseImage时还带images见 updateFormValue交互差异多文件模式渲染为可移除的文件列表每项带解析中/错误状态提示与删除按钮单文件模式则是简化版拖拽区见 render。达到maxLength后拖拽区会禁用is-disabled样式并弹出提示。解析图片parseImage 与 imageDataURI2.6.0 及以上版本通过配置parseImage来支持解析 Excel 里的图片{ type: form, api: /api/mock2/form/saveForm, debug: true, body: [ { type: input-excel, name: excel, parseImage: true, label: 上传 Excel } ] }默认情况下解析结果是 data URI 格式data:image/png;base64,...如果不想要这个前缀可以通过imageDataURI: false关闭此时只输出纯 base64 字符串。源码上图片解析由readImages完成通过worksheet.getImages()拿到工作表内嵌图片再用workbook.getImage(image.imageId)取出二进制 buffer经encodeBase64Bytes基于btoa编码后按imageDataURI决定是否拼接data:image/${extension};base64,前缀最终图片集合挂在该 sheet 结果的images字段上见 InputExcel.tsx。富文本模式plainText: false默认情况下 Excel 内容会解析为纯文本超链接取链接地址、公式取计算结果、错误值置空、富文本拼接为字符串。如果要保留富文本格式可以通过plainText属性控制{ type: form, api: /api/mock2/form/saveForm, debug: true, body: [ { type: input-excel, name: excel, plainText: false, label: 上传 Excel } ] }开启这个模式后对于富文本的内容会解析成对象的形式主要有以下几种富文本内容放在richText属性下{ richText: [ {text: This is }, {font: {italic: true}, text: italic} ] }出错{ error: #N/A }公式{ formula: A1A2, result: 7 };超链接{ text: www.mylink.com, hyperlink: http://www.mylink.com, tooltip: www.mylink.com }对应源码逻辑plainText为true时readWorksheet会对Hyperlink/Formula/RichText/Error四种单元格类型做降维处理超链接取hyperlink且剥掉mailto:前缀、公式取result、富文本经richText2PlainString拼接、错误值置空串为false时则原样保留 exceljs 返回的富文本对象见 InputExcel.tsx。解析文件名称autoFill 自动填充3.5.0 及以上版本文件解析成功后可以使用autoFill属性在当前组件所在的数据域中填充值。input-excel组件特有的保留字段定义如下InputExcelData中的字段可以用变量获取通常可以利用这个属性为input-excel所在的表单追加文件名称interface InputExcelData { /* 文件名称 */ filename: string; }{ type: form, api: /api/mock2/form/saveForm, debug: true, body: [ { type: input-excel, name: excel, label: 上传 Excel, autoFill: { operator: amis, time: ${DATETOSTR(NOW(), YYYY-MM-DD HH:mm:ss)}, fileName: ${filename} } } ] }实现上autoFill的填充由syncAutoFill完成它会先剔除与组件自身name同名的键避免覆盖 Excel 数据本身再支持 amis 表达式最后通过表单的onBulkChange批量写入数据域对已有值同为纯对象的字段还会做深度merge而非覆盖见 InputExcel.tsx。多文件模式下模板上下文会额外提供items所有已解析文件的{filename, data}数组与currentFile当前文件便于按文件维度填充。属性表属性名类型默认值说明版本allSheetsbooleanfalse是否解析所有 sheetparseModearray或objectobject解析模式includeEmptybooleantrue是否包含空值plainTextbooleantrue是否解析为纯文本parseImagebooleanfalse是否解析 Excel 中的图片2.6.0imageDataURIbooleantrue图片解析结果使用 data URI 格式2.6.0placeholderstring拖拽 Excel 到这或点击上传占位文本提示2.8.1autoFillRecordstring, string自动填充3.5.0multiplebooleanfalse解析多个文件6.13.0maxLengthnumber解析文件最大数6.13.0上表中默认值与 InputExcel.tsx 中defaultProps完全一致allSheets: false, parseMode: object, includeEmpty: true, plainText: true, parseImage: false, imageDataURI: true。其中includeEmpty在object模式下决定是否为表头声明的每个字段预置空字符串——true时即使某行为空也会在对象里保留所有键false时对象只包含有值的列组件的 TS 类型定义为AMISInputExcelSchema包含上述全部配置项见 InputExcel.tsxplaceholder的默认文案来自 locale 资源Excel.placeholder: 拖拽 Excel 到这或点击上传见 zh-CN.ts。事件表当前组件会对外派发以下事件可以通过onEvent来监听这些事件并通过actions来配置执行的动作在actions中可以通过${事件参数名}或${event.data.[事件参数名]}来获取事件产生的数据详细请查看事件动作。[name]表示当前组件绑定的名称即name属性如果没有配置name属性则通过value取值。事件名称事件参数说明change[name]: Arrayobject组件的值excel 解析后的数据excel 上传解析完成后触发源码中change事件在updateFormValue里派发且派发结果可以被preventDefault拦截——若被拦截则不会执行onChange也就是说你可以在onEvent中校验数据后阻止其写回表单见 InputExcel.tsx。动作表当前组件对外暴露以下特性动作其他组件可以通过指定actionType: 动作名称、componentId: 该组件id来触发这些动作动作配置可以通过args: {动作配置项名称: xxx}来配置具体的参数详细请查看事件动作。动作名称动作配置说明clear-清空reset-将值重置为初始值。6.3.0 及以下版本为resetValuesetValuevalue: Arrayobject更新的 excel 解析后数据更新数据clear{ type: form, debug: true, body: [ { type: input-excel, name: excel, label: 上传 Excel, id: clear_text }, { type: button, label: 清空, onEvent: { click: { actions: [ { actionType: clear, componentId: clear_text } ] } } } ] }reset如果配置了resetValue则重置时使用resetValue的值否则使用初始值。{ type: form, debug: true, body: [ { type: input-excel, name: excel, label: 上传 Excel, id: reset_text, value: [ { ID: 1, NAME: amis } ] }, { type: button, label: 重置, onEvent: { click: { actions: [ { actionType: reset, componentId: reset_text } ] } } } ] }setValue{ type: form, debug: true, body: [ { type: input-excel, name: excel, label: 上传 Excel, id: setvalue_text }, { type: button, label: 赋值, onEvent: { click: { actions: [ { actionType: setValue, componentId: setvalue_text, args: { value: [ { ID: 1, NAME: amis } ] } } ] } } } ] }源码剖析双引擎解析链路与文件格式策略input-excel底层依赖两个第三方库均声明在 package.json 中exceljs ^4.4.0xlsx 解析引擎与xlsx ^0.18.5xls 转换引擎交互层则基于react-dropzone实现拖拽上传accept.xlsx,.xls。完整的解析调用链为读取文件handleDrop接收文件后进入pending状态processExcelFile用FileReader.readAsArrayBuffer读取二进制内容格式分流按文件名后缀判断——.xls文件会先动态import(xlsx)经XLSX.read(..., {cellDates: true})载入工作簿再用XLSX.writeXLSX转成 xlsx 的 Array 缓冲.xlsx则直接使用原始 ArrayBuffer见 processExcelFile。这一xls 先转 xlsx、统一交给 exceljs的策略正是 2.10.0 起支持 xls 的实现基础动态加载解析引擎parseExcelData中通过await import(exceljs)懒加载 exceljs 并workbook.xlsx.load(data)载入工作簿两个重型依赖均为按需加载不占用首屏按配置产出数据allSheets走parseAllSheets遍历所有非隐藏 sheet否则取第一个非隐藏工作表parseImage为真时额外调用readImages收集内嵌图片。文件生命周期通过ExcelFileState类型管理init | error | pending | parsed | invalid每个文件独立持有状态与错误信息任一文件解析失败只标记该文件为error并展示错误消息locale 键Excel.parseError不会阻断其他文件的解析。这一设计在多文件批量导入场景中比较关键。从源码结构看doAction当前显式实现了clear置空值与reset优先取formStore.pristine中该name的初始值其次取resetValue见 InputExcel.tsx组件值被外部置空时也会同步清空内部文件列表componentDidUpdate中的处理。测试用例与行为验证组件行为由 InputExcel.test.tsx 覆盖验证了本文涉及的核心配置路径基本配置渲染、maxLength限制、allSheets: true、parseMode: array含includeEmpty: false、parseImage: trueimageDataURI: true等配置下的上传流程通过 mockFile与DataTransfer模拟拖拽上传多文件模式下文件列表的移除操作.cxd-ExcelControl-clear删除按钮disabled状态下拖拽区带is-disabled样式且不可交互placeholder自定义文案渲染autoFill场景下表单数据域中data.excel[0].班级、data.excel[0].姓名等变量可被同表单的其他控件消费断言fillClass为1班、fillName为张三与上文 autoFill 的用法相互印证。使用注意事项列名即字段名object模式下第一行单元格内容会被直接用作对象的键列名重复时后者会覆盖前者配合input-table时列name必须与之一致首行是表头object模式会消耗第一行作为字段名如果你的 Excel 没有表头行应改用parseMode: arrayhidden sheet 会被跳过无论单 sheet 还是allSheets模式隐藏的工作表都不参与解析多文件是追加语义multiple: true时重复拖入文件会累积受maxLength约束而单文件模式是替换语义设计表单时需注意两者差异change 事件可拦截解析完成派发change时支持preventDefault适合在写回表单前做二次校验。【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考