vue项目+xlsx+xlsx-style 实现table导出为excel的功能

最近遇到一个需求,后端提供一组数据,根据这组数据,导出为一个excel表格。

步骤如下:

1. 导出内容的预览如下:包含单元格的合并等操作。

2. 点击右下角导出按钮,可以直接下载一个excel表格。


由于我之前有用过csdn版本的xlsx-style,因此首先想到的就是使用xlsx来实现此功能。

下面介绍详细步骤:

1.安装xlsxxlsx-style

依次安装以下的内容:
npm install xlsx --save
npm install xlsx-style --save

2.局部注册使用

由于我这边是单个页面使用此功能,因此并没有在main.js中全局注册

局部注册的方法:

import * as XLSX from 'xlsx';
import * as XLSX2 from 'xlsx-style';

注意:一定要重命名其中的方法,就是用as 重命名,因为两个插件导出的名字默认都叫XLSX,如果不进行重命名,则会报错

3. vue.config.js中需要添加以下配置


如果不添加下面的代码,则运行时,代码会报错。

config.externals = {'./cptable': 'var cptable',
};

4.html预览用table组件来实现(VUE)


我对上面的表格进行了拆分,一个table里面包含了4组<thead></thead><tbody></tbody>
合并单元格 我使用的是colspan="n"

<table border="1" width="100%" cellspacing="0" cellpadding="0" id="tableId"><thead><tr><th colspan="7" class="headerCls">{{ info.saleOrderCode }}采购需求清单</th></tr></thead><tbody><tr><td>计划套数</td><td colspan="2">{{ info.producePlansCount }}</td><td>付款时间</td><td colspan="3">{{ info.lastPaidTime }}</td></tr><tr><td>申请时间</td><td colspan="2">{{ info.applicantTime }}</td><td>申请人员</td><td colspan="3">{{ info.applicantName }}</td></tr><tr><td>计划交期</td><td colspan="2">{{ info.deliveryTime }}</td><td>打印时间</td><td colspan="3">{{ info.printTime }}</td></tr></tbody><thead><tr><th colspan="5" class="leftTitCls">板材需求明细</th><th>板材系数</th><th>1.2</th></tr></thead><tbody><tr><td>序号</td><td>物品名称</td><td>型号规格</td><td>数量</td><td>单位</td><td>到货时间</td><td>备注</td></tr><tr v-for="(item, index) in list1" :key="item.materialName"><td>{{ index + 1 }}</td><td>{{ item.materialName }}</td><td>{{ item.specification }}</td><td>{{ item.procurementCount }}</td><td>{{ item.unit }}</td><td>{{ item.arrivalTime }}</td><td>{{ item.remark }}</td></tr></tbody><thead><tr><th colspan="5" class="leftTitCls">塑粉需求明细</th><th>喷涂系数</th><th>0.8</th></tr></thead><tbody><tr><td>序号</td><td>物品名称</td><td>型号规格</td><td>数量</td><td>单位</td><td>到货时间</td><td>备注</td></tr><tr v-for="(item, index) in list2" :key="item.materialName"><td>{{ index + 1 }}</td><td>{{ item.materialName }}</td><td>{{ item.specification }}</td><td>{{ item.procurementCount }}</td><td>{{ item.unit }}</td><td>{{ item.arrivalTime }}</td><td>{{ item.remark }}</td></tr></tbody><thead><tr><th colspan="7" class="leftTitCls">外购件需求明细</th></tr></thead><tbody><tr><td>序号</td><td>物品名称</td><td>型号规格</td><td>数量</td><td>单位</td><td>到货时间</td><td>备注</td></tr><tr v-for="(item, index) in list3" :key="item.materialName"><td>{{ index + 1 }}</td><td>{{ item.materialName }}</td><td>{{ item.specification }}</td><td>{{ item.procurementCount }}</td><td>{{ item.unit }}</td><td>{{ item.arrivalTime }}</td><td>{{ item.remark }}</td></tr></tbody></table>

5.导出功能(!!!重要)

数据渲染是通过数组遍历的。

//获取当前时间,用于命名excel表格
let time = this.moment(new Date()).format('YYYY-MM-DD');
//获取整个表格的行数。三个数组长度+其他固定行数(10)
let len = this.list1.length + this.list2.length + this.list3.length + 10;
this.tableToExcel('tableId',`${this.info.saleOrderCode}采购清单需求表${time}`,7,len,1
);

5.1 tableToExcel方法——入参(表格id,导出文档名称,列数,行数,表头行数)

this.tableToExcel( 'tableId', `采购清单需求表${time}`, 7,len, 1);
tableToExcel(tableId, fileName, headLength, colsLength, headColsLength) {var sheet = XLSX.utils.table_to_sheet(document.querySelector('#' + tableId));//根据tableId获取到元素,通过XLSX.utils.table_to_sheet 获取到sheet表格属性console.log(sheet);//下面是固定写法,可以直接照搬var arr = [];for (let i = 0; i < headLength; i++) {if (i < 26) {arr.push(String.fromCharCode(65 + i).toUpperCase());} else {arr.push('A' + String.fromCharCode(65 + (i - 26)).toUpperCase());}}for (let i = 0; i < arr.length; i++) {//如果是多级表头的话,设置单元格宽度if (headColsLength > 1) {for (let j = 0; j < headColsLength; j++) {if (j < headColsLength && sheet[arr[i] + j]) {if (!sheet[arr[i] + (j + 1)] ||!sheet[arr[i] + (j - 1)] ||(!sheet[arr[i] + (j - 1)] && !sheet[arr[i] + (j + 1)])) {sheet['!cols'].push({wch: sheet[arr[i] + j].v.length * 2 + 3,});}}}} else {//由于我这边是单个表头,因此走这块代码if (!sheet['!cols']) {sheet['!cols'] = [];}//我这边是对 A D E三列要求宽度窄一些,其他的宽一些,主要是根据内容的多少来,也可以根据内容的长度来处理if ((arr[i] + '1').indexOf('A') > -1 ||(arr[i] + '1').indexOf('D') > -1 ||(arr[i] + '1').indexOf('E') > -1) {sheet['!cols'].push({wch: 8,});} else {sheet['!cols'].push({wch: 14,});}}//由于我这边合并单元格后,导致部分边框不展示了,因此通过这个方法来补充边框。sheet = this.addRangeBorder(sheet['!merges'], sheet);//如果仅仅用上面的方法,发现还是有缺失的边框,因此下面又进行了一遍处理。添加边框及其他样式的处理。for (let key in sheet) {if (sheet[key] instanceof Object) {sheet[key].s = {border: {top: {style: 'thin',},bottom: {style: 'thin',},left: {style: 'thin',},right: {style: 'thin',},},alignment: {horizontal: 'center',vertical: 'center',wrap_text: true,},font: {sz: 11,},bold: true,numFmt: 0,};}}}this.downloadExcel(this.sheet2blob(sheet), `${fileName}.xlsx`); //下载},

5.2 解决合并单元格后部分边框消失问题——addRangeBorder

addRangeBorder(range, ws) {// s:起始位置,e:结束位置var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];range.forEach((item) => {var startRowNumber = Number(item.s.r),startColumnNumber = Number(item.s.c),endColumnNumber = Number(item.e.c),endRowNumber = Number(item.e.r);console.log('startColumnNumber',startColumnNumber,endColumnNumber,startRowNumber,endRowNumber);// 合并单元格时会丢失边框样式,例如A1->A4 此时内容在A1 而range内获取到的是从0开始的,所以开始行数要+2for (var i = startColumnNumber; i <= endColumnNumber + 2; i++) {for (var j = startRowNumber; j <= endRowNumber + 2; j++) {if (ws[arr[i] + j]) {ws[arr[i] + j].s = {border: {top: { style: 'thin' },left: { style: 'thin' },bottom: { style: 'thin' },right: { style: 'thin' },},alignment: {horizontal: 'center',vertical: 'center',wrap_text: true,},font: {sz: 11,},bold: true,numFmt: 0,};} else {ws[arr[i] + j] = {s: {border: {top: { style: 'thin' },left: { style: 'thin' },bottom: { style: 'thin' },right: { style: 'thin' },},alignment: {horizontal: 'center',vertical: 'center',wrap_text: true,},font: {sz: 11,},bold: true,numFmt: 0,},t: '',v: '',};}}}});return ws;},

5.3 sheet表格转化为文档流blob

 sheet2blob(sheet, sheetName) {sheetName = sheetName || 'sheet1';var workbook = {SheetNames: [sheetName],Sheets: {},};workbook.Sheets[sheetName] = sheet;var wopts = {bookType: 'xlsx',bookSST: false,type: 'binary',};var wbout = XLSX2.write(workbook, wopts);var blob = new Blob([this.s2ab(wbout)], {type: 'application/octet-stream',});return blob;},s2ab(s) {var buf = new ArrayBuffer(s.length);var view = new Uint8Array(buf);for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;return buf;},

5.4 下载excel文档

 downloadExcel(url, saveName) {var blob = new Blob([url], {type: 'application/octet-stream',});var a = document.createElement('a');a.id = 'downloadFtsetBtn';a.style.display = 'none';a.target = '_blank';document.body.appendChild(a);try {var URL = window.URL || window.webkitURL;a.href = URL.createObjectURL(blob);a.download = saveName;if (typeof navigator.msSaveBlob == 'function') {//IEnavigator.msSaveBlob(blob, saveName);}a.click();} catch (e) {console.log(e);}},

完成!!!多多积累,多多收获!!!

vue项目+xlsx+xlsx-style 实现table导出为excel的功能——技能提升相关推荐

  1. 使用js代码将HTML Table导出为Excel

    使用js代码将HTML Table导出为Excel的方法: 直接上源码 <html> <head> <meta http-equiv="Content-Type ...

  2. 如何将html表格导出到excel,html 页面导出到excel表格数据类型-如何将html里面的table导出成excel...

    怎么把html导出到excel表格 1先,我们打开要转换成THML的表格文件.下是我用的WPS2019版截图,EXCEL软件操作上差不多 2.接下来,点击左上角的[文件] 3.在[文件]菜单里找到并点 ...

  3. 4.Vue项目中下载本地pd、word、excel文件

    记录:Vue项目中下载本地pdf.word.excel文件 今日的一个需求是下载导入模板文件,该模板文件不是接口请求获取,而是本地的文件 该文章属转载:Vue下载本地pdf.word.excel文件 ...

  4. Jquery中使用table2excel插件实现将Html的table导出为Excel(附示例代码和资源下载)

    场景 jquery-table2excel是一款可以将HTML表格的内容导出到微软Excel电子表格中的jQuery插件. 效果 在Html中有一个表格 点击导出按钮 将其导出后 注: 博客: htt ...

  5. C# html的Table导出到Excel中

    C#中导出Excel分为两大类.一类是Winform的,一类是Web.今天说的这一种是Web中的一种,把页面上的Table部分导出到Excel中. Table导出Excel,简单点说,分为以下几步: ...

  6. VUE项目开发,使用canvas实现图片签名编辑手写板功能

    vue项目使用canvas实现手写板功能 完整的效果图如下: 直接上代码,下面代码可以当做组件直接引用,根据自己的需求传对应的图片即可,操作图标需要自己替换,保存功能也需要自己实现. CanvasDi ...

  7. 将table导出为excel格式文件

    html: <table cellpadding="0" cellspacing="0" class="data_table" id= ...

  8. vue项目中 axios请求拦截器与取消pending请求功能 - 年少、 - 博客园

    在开发vue项目中,请求是不可缺少的,在发送请求时常常需要统一处理一些请求头参数等设置与响应事件,这时利用请求拦截器再好不过. 这里以axios请求为例 实现了设置统一请求头添加token, 其中to ...

  9. table导出成excel

    今天给大家介绍一款将页面表格直接可以导出成excel的js插件,插件名称为tableExport,原地址为:https://github.com/hhurz/tableExport.jquery.pl ...

最新文章

  1. 选 Offer 的 5 个维度
  2. GitLab CI/CD 基础教程(三)
  3. DDNS 的工作原理及其在 Linux 上的实现--转
  4. linux命令编译C语言程序
  5. 分区安装linux,怎样安装Linux?
  6. 2014/9/12 play with thesick siyang baby.
  7. 性能测试培训: 监控CPU之python
  8. 小程序坑集【日常总结,持续更新(11.08更新)】
  9. DaDa英语宣布12月31日起全面停止所有外教服务
  10. 广告传媒实际税负怎么计算_建材销售类营业额3亿,缺进项致税负高?成立4家独资企业节税90%...
  11. Reflector反编译winform心得
  12. LinkedList 真的是查找慢增删快?刷新你的认知!
  13. 去除点击链接时出现的虚线框
  14. 时间表达式java定时器_quartz定时任务时间表达式说明
  15. 定义Student类,该类中有Sting name和int age两个属性,该类实现Comparable接口,实现根据学生姓名和年龄排序,该类重写toString()输出学生的姓名和年龄。
  16. NVIDIA GeForce Experience登录报错:验证程序加载失败,请检查您的浏览器设置,例如广告拦截程序(解决办法)
  17. java apache commons_Apache commons(Java常用工具包)简介
  18. yolov1原文地址以及论文翻译
  19. Sublime插件安装
  20. 6.30滴滴面经(一面+二面)

热门文章

  1. 【小程序专栏】多种开发方式对比-跨端?低代码?原生?还是云开发?
  2. 霍尔传感器-接近开关-门磁的使用
  3. 迅雷7下载百度云盘文件
  4. Win7 下哪个浏览器最好用
  5. 雷建平搜狐号创作者大会演讲:成为互联网产业的记录者
  6. 以UES为例,分析区块链目前的发展现状
  7. PMP报考时间一般都是什么时候?
  8. 这一代墨仓式新品可能更加符合家庭用户胃口
  9. Java从键盘上输入与输出
  10. 视频教程-AngularJS基础入门视频课程-AngularJS