文章目录

  • 背景
  • 技术选型
    • 1.xlsx(`不满足`)
    • 2.xlsx-style(`不推荐,后期问题太多`)
    • 3.lay-excel(`推荐`)
  • 一、准备内容数据
  • 二、准备表头数据
  • 三、认识lay-excel的导出方法
  • 四、无样式无合并的简单导出实现
  • 五、设置列宽
  • 六 合并表头
  • 七、设置表头样式
    • 设置公共样式的变量
    • 设置表头样式的所有代码
  • 八、设置内容样式
  • 九、设置行高
  • 十、表尾合并数据
  • 总结

背景

工作中遇到这么一个场景,一个统计页面且不带分页的表格,需要excel导出,excel导出一般是由后端导出,然后前端请求头携带Blob信息进行下载即可,此处由于没有分页,且甲方单位对excel导出的样式有要求,于是尝试使用纯前端excel导出,且elementUI、vxe-table等UI库均不能实现excel的样式的修改,需要自己实现样式修改的功能;先看下阅读本文后能实现的效果图如下:


技术选型

1.xlsx(不满足

较为老牌的excel操作库,且不支持样式修改(不满足
xlsx官网

2.xlsx-style(不推荐,后期问题太多

虽然能修改样式,但是已经停止维护,npm库查看最后一次更新已经是7年前;
且对vite构建工具不友好,包的引入,打包均会报错,实在不推荐
xlsx-style官网

3.lay-excel(推荐)

也就是老牌框架layUI的excel导出模块,基于xlsx实现,且有部分函数进行二次封装,且能修改样式;
lay-excel官方文档


一、准备内容数据

篇幅有限,只展示部分数据,此数据不包含表头数据

const body = [{company: '东莞市XXX股份有限公司',yearNo: '2001',total_online: '338',total_offline: '1571',permanent_online: '218',permanent_offline: '998',long_online: '77',long_offline: '372',short_online: '43',short_offline: '201',thirty_online: '0',thirty_offline: '0',decade_online: '0',decade_offline: '0',five_online: '0',five_offline: '0',},{company: '肇庆市XXX股份有限公司',yearNo: '2002',total_online: '1001',total_offline: '5901',permanent_online: '397',permanent_offline: '2867',long_online: '390',long_offline: '2196',short_online: '214',short_offline: '838',thirty_online: '0',thirty_offline: '0',decade_online: '0',decade_offline: '0',five_online: '0',five_offline: '0',},{company: '韶关市XXX股份有限公司',yearNo: '2003',total_online: '2665',total_offline: '12009',permanent_online: '491',permanent_offline: '3086',long_online: '1327',long_offline: '6024',short_online: '847',short_offline: '2899',thirty_online: '0',thirty_offline: '0',decade_online: '0',decade_offline: '0',five_online: '0',five_offline: '0',}]

二、准备表头数据

值得注意 的是,数据的字段必须与内容的字段一致,遇到有需要合并的表头,可以设置成空字符串’‘,如下文的total_offline:’',total_offline和total_online这2列的表头是需要合并到同一列的,也就是合计是占两列的;

header: [{company: '机构',yearNo: '年度',total_online: '合计',total_offline: '',permanent_online: '永久',permanent_offline: '',long_online: '长期',long_offline: '',short_online: '短期',short_offline: '',thirty_online: '30年',thirty_offline: '',decade_online: '10年',decade_offline: '',five_online: '5年',five_offline: '',},{company: '',yearNo: '',total_online: '线上销售',total_offline: '线下销售',permanent_online: '线上销售',permanent_offline: '线下销售',long_online: '线上销售',long_offline: '线下销售',short_online: '线上销售',short_offline: '线下销售',thirty_online: '线上销售',thirty_offline: '线下销售',decade_online: '线上销售',decade_offline: '线下销售',five_online: '线上销售',five_offline: '线下销售',},],

三、认识lay-excel的导出方法

也就是exportExcel方法,参数如下;


官网的简单示例

excel.exportExcel({sheet1: data,sheet2: data
}, '测试导出复杂表头.xlsx', 'xlsx', {extend: {// extend 中可以指定某个 sheet 的属性,如果不指定 sheet 则所有 sheet 套用同一套属性sheet1: {// 以下配置仅 sheet1 有效'!merges': mergeConf,'!cols': colConf,'!rows': rowConf}}
});

详细内容请查看官网


四、无样式无合并的简单导出实现

将表头数据和内容数据合并成一个数组后调用导出方法,效果如下

const clickNoStyleAndNotMagerEvt = () => {LAY_EXCEL.exportExcel([...header, ...body], '无样式无合并导出.xlsx', 'xlsx');};


五、设置列宽

makeColConfig是lay-excel基于excel二次封装后的方法,用于设置列宽;

值得注意的是,这个makeColConfig辅助函数用于一个与xlsx列配置项一致的数据格式,
此处如果只设置一个A:140的话只会A列生效;
如果再配置一个P:80的话,表示为A列宽140,P列宽80,剩下的A-P的范围默认使用第二个参数的80列宽;

  const clickColsEvt = () => {let colConf = LAY_EXCEL.makeColConfig({A: 140,P: 80,},80,);const option = {extend: {'!cols': colConf,},};LAY_EXCEL.exportExcel([...header, ...body], '设置列宽导出.xlsx', 'xlsx', option);};

六 合并表头

makeMergeConfig是lay-excel封装的一个辅助函数,需要传入一个二维数组;

如果A1,A2,A3三列合并的话,切记只需填写[‘A1’,‘A3’],无需填写三个元素,否则不生效;

  const clickMegerEvt = () => {const mergeArray = [['A1', 'A2'],//如果A1,A2,A3三列合并的话,切记只需填写['A1','A3'],无需填写三个元素,否则不生效['B1', 'B2'],['C1', 'D1'],['E1', 'F1'],['G1', 'H1'],['I1', 'J1'],['K1', 'L1'],['M1', 'N1'],['O1', 'P1'],];let colConf = LAY_EXCEL.makeColConfig({A: 140,P: 80,},80,);let mergeConf = LAY_EXCEL.makeMergeConfig(mergeArray);const option = {extend: {'!cols': colConf,'!merges': mergeConf,},};LAY_EXCEL.exportExcel([...header, ...body], '设置列宽导出.xlsx', 'xlsx', option);};

七、设置表头样式

使用的是setExportCellStyle方法,详细请查阅官网;

一开始就将表头和内容分别使用两个变量存储,为的就是此处,因为setExportCellStyle只能设置某个区间范围的值,所以此处会调用两次setExportCellStyle方法,一次针对表头,一次针对内容进行样式设置;

效果图如下:

设置公共样式的变量

因为需要设置2次样式,先定义处公共的样式出来

    //边框颜色变量const EXPORT_BORDER_COLOR = '2c3e50';//头部背景色变量const EXPORT_BACKGROUND_COLOR = '3462fd';// 头部字体颜色const EXPORT_HEADER_FONT_COLOR = 'ffffff';//公共样式变量const EXPORT_PUBLIC_STYLE = {s: {alignment: {//设置对齐方式horizontal: 'center',vertical: 'center',},border: {//设置边框top: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },bottom: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },left: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },right: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },},},};

设置表头样式的所有代码

  const clickHeaderStyleEvt = () => {//边框颜色变量const EXPORT_BORDER_COLOR = '2c3e50';//头部背景色变量const EXPORT_BACKGROUND_COLOR = '3462fd';// 头部字体颜色const EXPORT_HEADER_FONT_COLOR = 'ffffff';//公共样式变量const EXPORT_PUBLIC_STYLE = {s: {alignment: {//设置对齐方式horizontal: 'center',vertical: 'center',},border: {//设置边框top: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },bottom: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },left: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },right: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },},},};const mergeArray = [['A1', 'A2'], //如果A1,A2,A3三列合并的话,切记只需填写['A1','A3'],无需填写三个元素,否则不生效['B1', 'B2'],['C1', 'D1'],['E1', 'F1'],['G1', 'H1'],['I1', 'J1'],['K1', 'L1'],['M1', 'N1'],['O1', 'P1'],];//设置表头样式LAY_EXCEL.setExportCellStyle(header, undefined, {s: {fill: { bgColor: { indexed: 64 }, fgColor: { rgb: EXPORT_BACKGROUND_COLOR } },font: {color: { rgb: EXPORT_HEADER_FONT_COLOR },bold: true,},...EXPORT_PUBLIC_STYLE.s,},});//设置列宽let colConf = LAY_EXCEL.makeColConfig({A: 140,P: 80,},80,);//设置合并数据let mergeConf = LAY_EXCEL.makeMergeConfig(mergeArray);const option = {extend: {'!cols': colConf,'!merges': mergeConf,},};LAY_EXCEL.exportExcel([...header, ...body], '设置列宽导出.xlsx', 'xlsx', option);};

八、设置内容样式

如下图所示,内容区域也采用了居中对齐的方式了

  const clickBodyStyleEvt = () => {//边框颜色变量const EXPORT_BORDER_COLOR = '2c3e50';//头部背景色变量const EXPORT_BACKGROUND_COLOR = '3462fd';// 头部字体颜色const EXPORT_HEADER_FONT_COLOR = 'ffffff';//公共样式变量const EXPORT_PUBLIC_STYLE = {s: {alignment: {//设置对齐方式horizontal: 'center',vertical: 'center',},border: {//设置边框top: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },bottom: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },left: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },right: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },},},};const mergeArray = [['A1', 'A2'], //如果A1,A2,A3三列合并的话,切记只需填写['A1','A3'],无需填写三个元素,否则不生效['B1', 'B2'],['C1', 'D1'],['E1', 'F1'],['G1', 'H1'],['I1', 'J1'],['K1', 'L1'],['M1', 'N1'],['O1', 'P1'],];//设置表头样式LAY_EXCEL.setExportCellStyle(header, undefined, {s: {fill: { bgColor: { indexed: 64 }, fgColor: { rgb: EXPORT_BACKGROUND_COLOR } },font: {color: { rgb: EXPORT_HEADER_FONT_COLOR },bold: true,},...EXPORT_PUBLIC_STYLE.s,},});//设置内容样式LAY_EXCEL.setExportCellStyle(body, undefined, EXPORT_PUBLIC_STYLE);//设置列宽let colConf = LAY_EXCEL.makeColConfig({A: 140,P: 80,},80,);//设置合并数据let mergeConf = LAY_EXCEL.makeMergeConfig(mergeArray);const option = {extend: {'!cols': colConf,'!merges': mergeConf,},};LAY_EXCEL.exportExcel([...header, ...body], '设置列宽导出.xlsx', 'xlsx', option);};

九、设置行高

使用的是makeRowConfig辅助函数;详细情查阅官网;

  const clickRowStyleEvt = () => {//边框颜色变量const EXPORT_BORDER_COLOR = '2c3e50';//头部背景色变量const EXPORT_BACKGROUND_COLOR = '3462fd';// 头部字体颜色const EXPORT_HEADER_FONT_COLOR = 'ffffff';//公共样式变量const EXPORT_PUBLIC_STYLE = {s: {alignment: {//设置对齐方式horizontal: 'center',vertical: 'center',},border: {//设置边框top: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },bottom: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },left: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },right: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },},},};const mergeArray = [['A1', 'A2'], //如果A1,A2,A3三列合并的话,切记只需填写['A1','A3'],无需填写三个元素,否则不生效['B1', 'B2'],['C1', 'D1'],['E1', 'F1'],['G1', 'H1'],['I1', 'J1'],['K1', 'L1'],['M1', 'N1'],['O1', 'P1'],];//设置表头样式LAY_EXCEL.setExportCellStyle(header, undefined, {s: {fill: { bgColor: { indexed: 64 }, fgColor: { rgb: EXPORT_BACKGROUND_COLOR } },font: {color: { rgb: EXPORT_HEADER_FONT_COLOR },bold: true,},...EXPORT_PUBLIC_STYLE.s,},});//设置列宽let colConf = LAY_EXCEL.makeColConfig({A: 140,P: 80,},80,);//设置行高let rowConf = LAY_EXCEL.makeRowConfig({1: 30,2: 30,},20,);//设置内容样式LAY_EXCEL.setExportCellStyle(body, undefined, EXPORT_PUBLIC_STYLE);//设置合并数据let mergeConf = LAY_EXCEL.makeMergeConfig(mergeArray);const option = {extend: {'!cols': colConf,'!merges': mergeConf,'!rows': rowConf,},};LAY_EXCEL.exportExcel([...header, ...body], '销售数据导出.xlsx', 'xlsx', option);};

十、表尾合并数据

首先定义一个配置表尾合并的变量

    ///表尾合并的变量const footerConfig = {exclude: ['company', 'yearNo'], //这几个列不用合计merge: [['A', 'B']], //表尾需要合并的二维数组text: '合计', //不用合计的列显示的文案};

再定义一个合并的方法

 /***  表尾处理函数* @param {*} data 内容* @param {*} header 表头* @param {*} option 表尾合并项* @param {*} mergeArr 合并的二维数组*/const handleSum = (data, header, option, mergeArr) => {const _needSumArr = Object.assign([], data);if (!option) {return;}if (!_needSumArr || _needSumArr.length == 0) return;const _tmp = {};// Object.keys遍历获取到所有字段Object.keys(_needSumArr[0]).forEach((key) => {// 使用map处理成一维数字_tmp[key] = 0;_needSumArr.forEach((item) => {if (!option.exclude.includes(key)) {if (!isNaN(item[key])) {_tmp[key] += Number(item[key]);} else {_tmp[key] = NaN;}} else {_tmp[key] = option.text;}});});//处理是需要合并的列if (option.merge.length > 0) {const lenth = header.length + data.length; //表头+内容的长度const merge = option.merge.map((item) => {return item.map((col) => {return col + (lenth + 1);});});merge && merge.length > 0 && mergeArr.push(...merge);}data.push(_tmp);};

最终所有章节的代码

  const clickFooterEvt = () => {//边框颜色变量const EXPORT_BORDER_COLOR = '2c3e50';//头部背景色变量const EXPORT_BACKGROUND_COLOR = '3462fd';// 头部字体颜色const EXPORT_HEADER_FONT_COLOR = 'ffffff';//公共样式变量const EXPORT_PUBLIC_STYLE = {s: {alignment: {//设置对齐方式horizontal: 'center',vertical: 'center',},border: {//设置边框top: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },bottom: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },left: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },right: { style: 'thin', color: { rgb: EXPORT_BORDER_COLOR } },},},};const mergeArray = [['A1', 'A2'], //如果A1,A2,A3三列合并的话,切记只需填写['A1','A3'],无需填写三个元素,否则不生效['B1', 'B2'],['C1', 'D1'],['E1', 'F1'],['G1', 'H1'],['I1', 'J1'],['K1', 'L1'],['M1', 'N1'],['O1', 'P1'],];//设置表头样式LAY_EXCEL.setExportCellStyle(header, undefined, {s: {fill: { bgColor: { indexed: 64 }, fgColor: { rgb: EXPORT_BACKGROUND_COLOR } },font: {color: { rgb: EXPORT_HEADER_FONT_COLOR },bold: true,},...EXPORT_PUBLIC_STYLE.s,},});//设置列宽let colConf = LAY_EXCEL.makeColConfig({A: 140,P: 80,},80,);//设置行高let rowConf = LAY_EXCEL.makeRowConfig({1: 30,2: 30,},20,);///表尾合并的变量const footerConfig = {exclude: ['company', 'yearNo'], //这几个列不用合计merge: [['A', 'B']], //表尾需要合并的二维数组text: '合计', //不用合计的列显示的文案};handleSum(body, header, footerConfig, mergeArray);//设置内容样式LAY_EXCEL.setExportCellStyle(body, undefined, EXPORT_PUBLIC_STYLE);//设置合并数据let mergeConf = LAY_EXCEL.makeMergeConfig(mergeArray);const option = {extend: {'!cols': colConf,'!merges': mergeConf,'!rows': rowConf,},};LAY_EXCEL.exportExcel([...header, ...body], '销售数据导出.xlsx', 'xlsx', option);};

总结

以上章节都是分功能实现,只为论述每个章节内容,实际的运用还请二次封装成一个公共方法调用,否则代码冗余;

示例代码

纯前端excel导出相关推荐

  1. 纯前端JS导出Word包含图片

    纯前端JS导出Word包含图片 纯前端JS导出Word文档包含图片 Word导出方式 依赖 实现代码 纯前端JS导出Word文档包含图片 在做项目中,遇到一个需求,是将后台返回的属性以及URL图片导出 ...

  2. js-xlsx/xlsx-style 纯前端数据导出Excel且支持自定义样式

    前端开发过程中经常遇到导出excel的需求.这种情况大多数都是服务端处理数据(QAQ至少我遇到的大多数都是这样),然后返回一个链接,前端不需要管服务端怎么操作直接打开这个链接(window.locat ...

  3. excel在线_功能强大的纯前端 Excel 在线表格: Luckysheet

    [导语]:Luckysheet是一款类似excel的在线表格,纯前端,功能强大.配置简单.完全开源,几行代码就能展现出一个功能完备的在线表格. 简介 Luckysheet是一款类似excel的纯前端在 ...

  4. 关于纯前端excel上传、下载功能

    工作项目中,表格的上传下载基本都是调取后端接口,把处理逻辑放在后端进行处理.那么纯前端js代码实现excel的上传下载是否可行?其实代码逻辑很简单,不过需要引用xlsx.js进行处理.下面是我自己写的 ...

  5. js-xlsx 读取和导出excel实现前端 Excel 导出(支持多 sheet)

    之前写文章介绍了使用 js-xlsx 实现导入 excel 的功能,现在再介绍一下如何使用 js-xlsx 进行 excel 导出. [实现步骤] 1. 首先安装依赖 npm install xlsx ...

  6. 纯前端 vue 导出excel 这里用 vue-json-excel插件

    1.npm安装依赖 npm install vue-json-excel 2.项目主文件入口main.js全局引入 import JsonExcel from 'vue-json-excel'Vue. ...

  7. js vue 设置excel单元格样式_vue+elementui 项目纯前端Export2Excel导出excel,并利用xlsx-style设置单元格样式...

    1 /*eslint-disable*/ 2 require('script-loader!file-saver');3 require('./Blob.js'); //blob.js也是网上找的,下 ...

  8. 使用VUE+XLSX实现纯前端的导出Excel

    1. 安装需要的插件 npm i xlsx -S npm i xlsx-style -S npm i file-saver -S 安装完xlsx-style插件并引入后启动项目会报错 ./cptabl ...

  9. 前端excel导出适应中国式复杂报表

    前端问题记录 大家好,我是你们的好朋友程序猿:铭文 一.前端页面获取页面H5. 二.用一个插件来写非常得简单:js-xlsx 大家好,我是你们的好朋友程序猿:铭文 先简单的说下:领导给安排了一个活就是 ...

最新文章

  1. 替换openjdk的版本时遇到报错Transaction check error
  2. ijkplayer支持h264
  3. 拦截导弹 (加了神奇的位运算)
  4. 【数论】【杜教筛】选数(P3172)
  5. 阿克苏计算机考试成绩查询,阿克苏高考成绩查询系统2021
  6. linux 用vi命令的使用以及vi编辑后的后续保存退出等相关命令的使用
  7. Docker使用小结(二)Docker仓库 Docker数据管理 端口映射与容器互联
  8. Python学习笔记—Dict和set
  9. java.net.InetAddress 获取系统 MAC 地址 与 IP 地址
  10. 机器学习实战 2.3获取数据
  11. SVN下载安装及入门使用教程_win10_64位
  12. matlab图片模板匹配算法,基于Matlab-图像匹配——模板匹配.docx
  13. Windows+Caffe+VS2013+python接口配置过程
  14. 用VBA打开PDF文件
  15. Python春节特训营08:还记得大明湖畔的变量和函数吗
  16. you are in emergency mode解决办法
  17. 智能访客机要注意这些陷阱
  18. 传销?花生日记罚款7456万元这个微信社群营销分钱模式要知道
  19. 学习C++复合数据类型
  20. 学习数据数据结构的意义

热门文章

  1. “你们程序员不就是修电脑的吗,你牛什么牛,移动应用开发专业就业前景
  2. 三个丰盛:谋生、关系、内心
  3. 小学期实训-智慧电子时钟
  4. <python开发> python开发 环境搭建(windows)
  5. 流量兄弟和站群软件的较量
  6. 什么是序列,Python序列详解(包括序列类型和常用操作)
  7. java object类
  8. Performer:Rethinking Attention with Performers(2020-9-30)
  9. 国内外有名的居民与商务服务调查研究咨询公司
  10. 五邑电子信息工程插本_专插本电子信息工程专业