纯前端实现导出excel

项目背景:

vue2

插件:

xlsx;xlsx-style;file-saver

说明:

单独使用 xlsx插件,也可以将网页上的table导出成excel,但是导出的excel,没有样式

结合xlsx-style;file-saver,可以实现带样式的excel文件

具体实现代码:

import * as XLSX from 'xlsx'
import * as XLSXStyle from 'xlsx-style'

import XLSX_SAVE from 'file-saver'

export function exportToExcel(columns,dataSource,filename) {
  const headers = columns
    .filter(col => col.key !== 'operation') // 过滤掉 operation 列
    .map(col => col.title)
  const dataIndexes = columns
    .filter(col => col.key !== 'operation') // 过滤掉 operation 列
    .map(col => col.dataIndex)

  // 重构数据,使其匹配表头
  const data = dataSource.map((row,index) => {
    let newRow = {}
    dataIndexes.forEach((dataIndex, index) => {
      newRow[headers[index]] = row[dataIndex]
    })
    return newRow
  })

  // 将表头和数据合并
  data.unshift(headers.reduce((acc, cur) => ((acc[cur] = cur), acc), {}))

  // 将数据转换为工作表
  const worksheet = XLSX.utils.json_to_sheet(data, { skipHeader: true })

  // 设置整个表格的边框
  const range = XLSX.utils.decode_range(worksheet['!ref'])
  for (let R = range.s.r; R <= range.e.r; R++) {
    for (let C = range.s.c; C <= range.e.c; C++) {
      const cellAddress = XLSX.utils.encode_cell({ r: R, c: C })
      if (!worksheet[cellAddress]) {
        worksheet[cellAddress] = { t: 's', v: '' } // 新建空单元格对象
      }
      if (!worksheet[cellAddress].s) {
        worksheet[cellAddress].s = {} // 新建样式对象
      }
      worksheet[cellAddress].s.border = {
        top: { style: 'medium', color: { rgb: '000000' } },
        bottom: { style: 'medium', color: { rgb: '000000' } },
        left: { style: 'medium', color: { rgb: '000000' } },
        right: { style: 'medium', color: { rgb: '000000' } },
      }
    }
  }

  for(let i=0;i<columns.length;i++){
    const list = dataSource.map(item=>{
      const val = item[columns[i].dataIndex];
      if(val){
        if(columns[i].dataIndex == 'indexnum'){
          return 5;
        }else if(val.toString().charCodeAt(0) > 255){
          return val.toString().length * 2;
        }else{
          return val.toString().length;
        }
      }else{
        return 1;
      }
    })
    const maxLength = Math.max(list);
    const width = maxLength * 1.1;
    if(!worksheet["!cols"]) worksheet["!cols"] = [];
    if(!worksheet["!cols"][i]) worksheet["!cols"][i] = {wch:8};
    worksheet["!cols"][i].wch = width;
  }

  // 创建一个新的工作簿并将工作表添加到工作簿中
  const workbook = XLSX.utils.book_new()
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')

  // 导出工作簿为 Excel 文件
  // console.log('xlsx-style', XLSXStyle)
  let wbout = XLSXStyle.write(workbook, {
    type: 'binary',
    bookType: 'xlsx',
  });
  XLSX_SAVE.saveAs(
    new Blob([s2ab(wbout)], {
      type: 'application/octet-stream',
    }),
    `${filename}.xlsx`
  )
}

 使用时调用:

exportToExcel(columns,dataSource,'demo列表')

避坑:

安装xlsx-style后,在使用时,大概率会报错:

Can‘t resolve ‘./cptable‘ in ‘xxx\node_modules_xlsx

解决方式:

在根目录下的vue.config.js(没有的话自己创建一个) 

加入下面的代码

module.exports = {
	configureWebpack: {
    	externals: {
      		'./cptable': 'var cptable'
    	}
  	}
}

然后重启项目 

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值