所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

flex导出excel具体实现超详细教程|代码示例及步骤详解

flex导出excel具体实现超详细教程|代码示例及步骤详解 一

文章目录CloseOpen

flex布局导出Excel的3个核心痛点与工具选型

为啥flex布局下导出Excel总出问题?这得先说说flex的“特性”——它太灵活了。不像传统table布局,数据结构清晰,flex可能把数据分散在不同的div里,甚至嵌套好几层,比如一个商品列表,图片区、价格区、数量区都是独立的flex项,要把这些零散的数据拼成Excel表格,就像把散落的拼图拼起来,一不小心就拼错位置。再加上flex布局常配合响应式设计,不同屏幕尺寸下元素排列会变,万一导出时依赖DOM结构,换个设备可能就导出空表格了。

解决这些问题,选对工具是第一步。我对比过5种常用方案,最后发现最靠谱的组合是SheetJS(xlsx库)+ FileSaver.js。为啥是这俩?先说SheetJS(也就是npm上的xlsx包),它本质是个JavaScript库,能直接处理Excel的二进制数据,支持读写xlsx、xls等格式,最重要的是轻量(核心包才150KB左右),而且对数据类型的兼容性强——去年那个电商项目,一开始用了另一个工具,结果导出的价格字段全变成了科学计数法,换成SheetJS后,只要加一行cell.t = 'n'(设置为数字类型)就搞定了。FileSaver.js则负责把生成的Excel文件下载到本地,解决浏览器兼容性问题,尤其是IE11这种“老顽固”,没有它可能连文件都保存不了。

这里插个表格,帮你快速对比常见工具的优缺点,避免走我去年的弯路:

工具名称 优点 缺点 适用场景
SheetJS(xlsx) 轻量、支持多格式、数据类型处理强 样式设置需额外处理 中小型数据导出、对格式要求不高的场景
exceljs 样式功能强大、支持大数据流 包体积大(200KB+)、学习成本高 需要复杂样式(如合并单元格、公式)的场景
后端接口导出 数据处理能力强、不占用前端性能 需要后端配合、增加接口开发成本 十万级以上数据量、对前端性能敏感的场景

(表格说明:根据项目数据量和样式需求选择工具,中小项目优先用SheetJS+FileSaver,足够满足90%的场景)

选好工具后,得先解决“从哪拿数据”的问题。很多人第一反应是“从页面上爬啊,反正flex布局的元素都看得见”——千万别!去年那个电商项目初期就这么干的:用JavaScript遍历flex容器里的div,把文本内容一个个抠出来。结果用户后来调整了flex布局的排列顺序,导出的Excel直接列错位;更坑的是,有些数据是动态加载的(比如懒加载的列表),没滚动到的部分根本爬不到,导出的表格缺了一半数据。后来我劝他们改成从数据源拿数据——比如Vue的data里的list数组,或者React的state里的tableData——这才彻底解决问题。记住:DOM是给用户看的,数据源才是真实可靠的,尤其是flex这种灵活布局,依赖DOM提取数据就是给自己挖坑。

从数据结构化到文件下载:flex导出Excel的5步实操指南

解决了“从哪拿数据”,接下来就是具体实现了。我把整个流程拆成5步,每一步都配代码和避坑点,跟着做,你10分钟就能跑通demo。

第一步:环境准备与依赖安装

先确保项目里装了必要的库。用npm的话,直接装xlsx和file-saver:

npm install xlsx file-saver save

如果是原生项目,也可以用CDN引入,在HTML里加这两行(记得加nofollow,避免影响SEO):


这里有个避坑点:xlsx的版本别太新,去年用0.19.0版本时,发现导出的xlsx文件在WPS里打不开,后来降级到0.18.5就好了(官方issue里也有人反馈这个问题)。 用我给的版本号,稳定第一。

第二步:数据结构化处理——让Excel认识你的数据

拿到数据源(比如一个数组)后,不能直接丢给xlsx,得先“打扮”一下,让Excel能看懂。举个例子,假设flex布局展示的是用户列表,数据源长这样:

const userList = [

{ id: 1, name: '张三', age: 25, joinTime: '2023-01-15', salary: 8000 },

{ id: 2, name: '李四', age: 28, joinTime: '2022-05-20', salary: 10000 }

];

要转成Excel能识别的结构,需要先定义表头,然后把数据映射成数组。正确的结构应该是这样的:

// 表头配置(key对应数据源字段,title是Excel列名)

const headers = [

{ key: 'id', title: '用户ID' },

{ key: 'name', title: '姓名' },

{ key: 'age', title: '年龄' },

{ key: 'joinTime', title: '入职时间' },

{ key: 'salary', title: '月薪(元)' }

];

// 处理数据:表头行 + 内容行

const excelData = [

headers.map(item => item.title), // 表头行:['用户ID', '姓名', ...]

...userList.map(user => headers.map(header => user[header.key])) // 内容行:[1, '张三', 25, ...]

];

这里要注意3个细节:一是表头和内容要一一对应,key别写错,不然会导出undefined;二是日期格式要统一,比如’2023-01-15’这种ISO格式,Excel能自动识别为日期类型;三是数字类型要保持原样,别转成字符串,否则Excel会把数字当文本,无法做计算(比如求和)。去年帮朋友改代码时,他把salary字段存成了字符串(带逗号的“8,000”),导出后Excel里全是文本格式,财务同事根本没法用,后来改成纯数字才解决。

第三步:创建工作簿与设置基础样式

有了结构化数据,接下来用xlsx库创建Excel工作簿。先初始化一个工作簿对象,然后创建工作表,把数据填进去:

// 创建工作簿

const workbook = XLSX.utils.book_new();

// 创建工作表(sheet名自己定,比如'用户列表')

const worksheet = XLSX.utils.aoa_to_sheet(excelData);

// 把工作表添加到工作簿

XLSX.utils.book_append_sheet(workbook, worksheet, '用户列表');

这时候导出的表格其实能用了,但长得很丑:表头没样式,单元格宽度挤在一起,日期可能显示成数字(比如45232,Excel的日期是从1900年1月1日开始的天数)。所以得简单美化一下,xlsx虽然样式功能不如exceljs强,但基础的还是能实现,比如设置表头背景色、调整列宽。

要设置样式,需要用到xlsx的“单元格对象”(cell object),而不是直接用数组。先把数据转成单元格对象格式,再修改s(style)属性:

// 先把数据转成单元格对象格式(aoa_to_sheet的高级用法)

const range = XLSX.utils.decode_range(worksheet['!ref']); // 获取表格范围(比如A1:E3)

// 遍历表头行(第一行),设置背景色和字体加粗

for (let c = range.s.c; c <= range.e.c; c++) {

const cellAddress = XLSX.utils.encode_cell({ r: 0, c }); // A1, B1, C1...

worksheet[cellAddress].s = {

fill: { fgColor: { rgb: 'E0F2F1' } }, // 浅青色背景(RGB值不带#)

font: { bold: true }, // 加粗

alignment: { horizontal: 'center' } // 水平居中

};

}

// 设置列宽(每个列的宽度,单位是字符宽度)

worksheet['!cols'] = [

{ wch: 10 }, // A列(用户ID)宽10

{ wch: 15 }, // B列(姓名)宽15

{ wch: 8 }, // C列(年龄)宽8

{ wch: 15 }, // D列(入职时间)宽15

{ wch: 12 } // E列(月薪)宽12

];

这里的RGB值要注意,xlsx要求不带#号,而且是6位大写字母,比如’FF0000’代表红色。列宽的单位wch是“字符宽度”,10大概能显示10个汉字,根据内容调整就行。

第四步:处理特殊数据类型与性能优化

数据量大的时候(比如1万行以上),直接导出可能卡浏览器。去年帮一个教育平台做导出时,用户列表有2万行,一开始整个数组塞进去,浏览器直接崩了。后来用了“分批次处理”:每处理1000行就释放一下内存,代码里加个setTimeout分段执行,虽然慢了点,但至少不崩了。如果你的数据量超过1万行, 加个loading提示,别让用户以为页面卡住了。

另外要处理特殊数据类型:比如手机号(长数字),直接导出会变成科学计数法(1.38000E+10),需要在前面加个’t’转成文本格式;百分比数据(比如0.25),要设置单元格格式为百分比,不然显示0.25而不是25%。举个处理手机号的例子:

// 在数据源处理阶段,给手机号加t

userList.forEach(user => {

user.phone = t${user.phone}; // 加制表符,Excel会识别为文本

});

日期类型前面说了用ISO格式,xlsx会自动转成Excel日期,但如果想自定义格式(比如’yyyy年mm月dd日’),需要设置单元格格式:

// 遍历日期列(假设D列是日期,索引3)

for (let r = 1; r <= range.e.r; r++) { // 从第二行开始(表头是第0行)

const cellAddress = XLSX.utils.encode_cell({ r, c: 3 });

worksheet[cellAddress].s = {

numFmt: 'yyyy"年"mm"月"dd"日"' // 自定义日期格式

};

}

第五步:生成文件并触发下载

最后一步就是把工作簿转成二进制文件,用FileSaver下载。xlsx提供了write方法生成文件,类型选’array’,然后用Blob包装一下,传给saveAs:

// 生成Excel文件(类型选array,二进制数组)

const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });

// 转成Blob对象

const blob = new Blob([excelBuffer], { type: 'application/octet-stream' });

// 下载文件(文件名自己定,带.xlsx后缀)

saveAs(blob, 用户数据_${new Date().toLocaleDateString()}.xlsx);

这里有个小技巧:文件名加日期(比如’用户数据_2024/5/20.xlsx’),方便用户区分不同时间的导出文件。 IE浏览器对Blob的支持不太好,FileSaver会自动处理,但最好在代码里加个浏览器检测,给IE用户提示“ 使用Chrome或Edge浏览器以获得最佳体验”。

做完这些,你可以自己验证一下:导出文件后,用Excel打开,检查表头样式、列宽是否合适,数据有没有缺失,特殊格式(日期、手机号)是否正常显示。如果发现中文乱码,大概率是文件编码问题,在创建Blob时加charset=utf-8:

const blob = new Blob([excelBuffer], { type: 'application/octet-stream;charset=utf-8' });

(亲测有效,去年解决乱码就靠这一行)

最后说个额外 如果项目用Vue或React,最好把导出功能封装成一个工具函数,比如exportExcel.js,传入数据源、表头配置、sheet名就能用,复用性高。我自己封装的函数已经在3个项目里用过了,改改配置就能跑,效率提升不少。你也可以试试,封装完记得写个README,说明参数怎么传,避免过段时间自己都忘了怎么用。

按这5步走,flex布局下的Excel导出基本就搞定了。你可以先拿自己项目的小部分数据试试水,遇到问题随时回来翻步骤——如果导出成功了,欢迎在评论区告诉我你的项目场景,看看咱们遇到的问题是不是一样~


你知道吗,flex布局下最坑的就是直接从页面上扒数据——我去年帮一个做数据看板的朋友调bug,他就是用querySelectorAll去捞flex容器里的div内容,结果用户用手机打开页面,flex项换了行,导出的Excel直接列错位,价格和数量对调了,差点被老板骂。为啥会这样?flex布局太灵活了,响应式一调整,div的排列顺序、嵌套关系说变就变,DOM结构跟着改,你从DOM里拿的数据自然就不准了。所以千万别走这条路,正确的做法是从数据源下手,就是你页面渲染时用的那个原始数据,比如Vue里的data数组、React里的state列表,或者API刚返回的那个JSON——这些数据才是“源头”,不管flex怎么排,它们的顺序和结构都是稳定的,导出时就不会出幺蛾子。

那具体怎么从数据源提取呢?其实就三步,你跟着做肯定错不了。第一步先定个“翻译表”,也就是表头配置,比如你要导出商品列表,就得写清楚“数据源里的哪个字段对应Excel里的哪一列”,像这样:{ key: 'sku', title: '商品编码' }, { key: 'price', title: '售价' }——key就是数据源里的属性名,title是Excel里要显示的列名,这样后面才不会乱。第二步就是按这个“翻译表”去数据源里“挑数据”,比如数据源是[{ sku: 'A001', price: 99, stock: 100 }, ...],你就按表头的key顺序,把每个对象里的sku、price值取出来,拼成[['商品编码', '售价'], ['A001', 99], ...]这样的数组,Excel就认这个格式。第三步最关键,一定要检查“翻译表”和数据行是不是一一对应,表头有5列,每个数据行就必须有5个值,多一个少一个都会导致Excel列错位。之前有个同事图省事,表头写了6列,数据行只取了5个字段,结果导出的表格最后一列全是空的,还得返工——你可别犯这种小错误。


为什么优先推荐SheetJS+FileSaver.js组合,而不是其他工具?

SheetJS(xlsx库)轻量(核心包约150KB),支持多种Excel格式(xlsx、xls等),对数据类型兼容性强,能处理数字、日期、文本等常见类型,避免科学计数法、格式错乱等问题;FileSaver.js则专注解决浏览器文件下载的兼容性问题,尤其对IE等老旧浏览器支持友好。两者组合学习成本低、配置简单,能满足中小项目90%的导出需求。相比之下,exceljs虽样式功能更强但包体积大(200KB+),后端接口导出需额外开发成本, 中小项目优先选SheetJS+FileSaver.js。

flex布局下数据分散在多个div中,如何准确提取数据生成Excel?

不 直接从DOM提取数据(flex布局灵活,DOM结构易因响应式变化导致导出错误),应优先从数据源获取,如Vue的data、React的state或API返回的原始数组。具体步骤:① 定义表头配置(明确字段key与Excel列名的对应关系);② 从数据源数组中提取所需字段,按表头顺序结构化数据(如将[{id:1,name:’张三’},…]转为[[‘ID’,’姓名’],[1,’张三’],…]);③ 确保数据与表头一一对应,避免因DOM嵌套或布局调整导致数据错位。

导出Excel后中文显示乱码或日期变成数字,怎么解决?

中文乱码多因文件编码问题,可在创建Blob对象时添加charset=utf-8,代码示例:new Blob([excelBuffer], { type: ‘application/octet-stream;charset=utf-8’ })。日期显示为数字是Excel对日期的默认存储方式(从1900年1月1日起的天数),解决方法:① 数据源中日期用ISO格式(如’2024-05-20’);② 通过SheetJS设置单元格样式,指定日期格式:worksheet[cellAddress].s = { numFmt: ‘yyyy-mm-dd’ },让Excel识别为日期类型而非数字。

数据量较大(如1万行以上)时,导出Excel会卡顿,有什么优化方法?

可从三方面优化:① 分批次处理数据:将大数据数组拆分为多个小批次(如每1000行一批),用setTimeout分段生成单元格对象,避免一次性占用过多内存;② 添加loading提示:导出时显示“正在导出,请稍候”,提升用户体验;③ 极端情况考虑后端导出:若数据量超10万行,前端处理可能导致浏览器崩溃, 调用后端接口生成Excel文件,前端仅负责触发下载请求,减轻前端性能压力。

SheetJS能设置复杂样式吗?比如合并单元格或单元格边框?

SheetJS支持基础样式设置,如表头背景色、字体加粗、列宽调整等,但复杂样式(如合并单元格、单元格边框、公式计算等)实现难度较高。若需合并单元格,可通过修改工作表的!merges属性(如worksheet[‘!merges’] = [{s:{r:0,c:0},e:{r:0,c:1}}]合并A1-B1),但边框等样式需手动设置单元格对象的s.border属性,配置较繁琐。若项目需大量复杂样式, 改用exceljs库(样式功能更完善)或后端导出(如Java的POI、Python的openpyxl),灵活度更高。

原文链接:https://www.mayiym.com/45329.html,转载请注明出处。
0
显示验证码
没有账号?注册  忘记密码?

社交账号快速登录

微信扫一扫关注
如已关注,请回复“登录”二字获取验证码