vue3中Table导出Excel

项目中涉及到Table表格的很大概率会有需求是导出Excel,在项目中一般使用xlsx插件导出

思路

先来理一下实现这个需求的大纲
  1. 首先是安装插件并使用
  2. 获取到要导出的数据
  3. 编写导出方法
  4. 处理成xlsx插件接收的数据
  5. 导出表格定制化

安装插件

npm install xlsx
npm install xlsx-js-style --save
npm install file-saver --save

npm install xlsx
npm install xlsx-js-style --save
npm install file-saver --save

import * as XLSX from ‘xlsx’ //导XLSX插件
import XLSXJSStyle from ‘xlsx-js-style’ //定制化XLSX的样式插件
import FileSaver from ‘file-saver’ //添加样式后需要用fileSaver到处(如果不使用xlsx-js-style可以直接 用xlsx的导出方法)

import * as XLSX from 'xlsx' //导XLSX插件
import XLSXJSStyle from 'xlsx-js-style' //定制化XLSX的样式插件
import FileSaver from 'file-saver' //添加样式后需要用fileSaver到处(如果不使用xlsx-js-style可以直接用xlsx的导出方法)

获取到要导出的数据

我项目中用的antdv 所以这里就不过多展示

编写导出方法

我们的项目需求中要求合并单元格,具体数据格式后面展示

/**
 *
 * @param tableData 要导出的数据(必填)
 * @param columns 要导出的数据的表头(必填)因为是用的表格组件所以我这里直接传的就是table组件要求的columns
 * @param name  导出文件名称默认为test
 * @param sheetName
 * @param merges 要合并行/列 格式为 [{s:{r:x,c:x},e:{}}]
 */
export function exportExcel(
  tableData,
  columns,
  name = 'test',
  sheetName = 'sheetName',
  merges: any = [],
) {
    
    
  /* convert state to workbook */
  const data: any[] = []
  const keyArray: any[] = columns.map((item) => item.key) //获取key
  const titleArr: any[] = columns.map((item) => item.title) //获取表头
  // keyArray为英文字段表头
  tableData.forEach((item) => {
    
    
    const arr: any[] = keyArray.map((key) => {
    
    
      return item[key]
    })
    data.push(arr)
  })
  data.splice(0, 0, titleArr)
  // data.split(0,0,keyArray,titleArr) 如果需要英文表头的话
  console.log('data', data)
  const ws: any = XLSX.utils.aoa_to_sheet(data)
  const wb = XLSX.utils.book_new()
  // 此处隐藏英文字段表头
  // const wsrows = [{ hidden: true }]
  // ws['!rows'] = wsrows // ws - worksheet
  ws['!merges'] = merges
  console.log(ws)
  for (const key in ws) {
    
    
    if (key != '!rows' && key != '!merges' && key != '!ref') {
    
    
      ws[key].s = {
    
    
        alignment: {
    
    
          horizontal: 'center', //水平居中
          vertical: 'center', //垂直居中
        },
      }
    }
  }
  XLSX.utils.book_append_sheet(wb, ws, sheetName)
  const wbout = XLSXJSStyle.write(wb, {
    
     bookType: 'xlsx', bookSST: true, type: 'array' })
  try {
    
    
    FileSaver.saveAs(new Blob([wbout], {
    
     type: 'application/octet-stream' }), `${
      
      name}.xlsx`)
  } catch (error) {
    
    }
}

处理成xlsx想要的数据

我们的数据中是一条数据里某个字段是数组形式,所以导出的时候要根据这个字段拆分成对应数据,然后再把重复的字段合并,我以我们项目中的字段为例了就,数据格式如下

 [
    {
    
    
      createTime: '',
      deviceID: '',
      deviceSN: '',
      firewallVersion: '',
      lastActiveTime: '',
      online: '',
      productID: '',
      productName: '',
      projectList: [
        {
    
    
          projectAddress: '',
          projectID: '',
          projectName: '',
          projectShortName: '',
        },
      ],
    },
  ]
  //导出方法具体使用
  function exportSelectFun() {
    
    
    let tableData = JSON.parse(JSON.stringify(state.selectedRows))
    let {
    
     arr, merges } = formatData(tableData, true) //拆分数据,以及处理合并单元格的数据
    exportExcel(
      arr,
      [
        {
    
    
          title: '序号',
          dataIndex: 'index',
          key: 'index',
          ellipsis: true,
        },
        ...columns.filter((item) => item.key != 'operation'),
      ],
      '智能终端设备列表',
      'sheetName',
      merges,
    )
  }
  
  /** 
  *拆分数据以及处理数据
  *target 目标数据
  *flag 是否要拆分 
  */
  function formatData(target, flag = false) {
    
    
    let arr: any[] = []
    let merges: any[] = []
    target.forEach((item, index) => {
    
    
      let newArr = item.projectList.map((v) => {
    
    
        let obj = {
    
    
          ...item,
          ...v,
          index: index + 1,
        }
        obj.location = obj.projectAddress
        if (flag) {
    
    
          obj.monitorItemName = ''
          obj.monitorPointName = ''
          if (Array.isArray(obj.monitorPointList)) {
    
    
            obj.monitorItemName = removeDuplicates(
              obj.monitorPointList.map((point) => point.monitorItemName),
            )?.join(',')
            obj.monitorPointName = obj.monitorPointList
              .map((point) => point.monitorPointName)
              ?.join(',')
          }
        }
        return obj
      })
	  //调用getMerges生成合并的数据
	  //这里用的取巧的办法
	  // 1.start传的是arr的长度,因为每次循环都会把拆分的数据重新添加到arr中所以我们start就用arr.length
	  // 2.end参数传的是newArr的长度,因为每次拆分好的数据是newArr 所以我要合并单元格的结束位置就是这个newArr,首次的时候newArr.length,之后就要变成arr.length+length了
      if (arr.length == 0) {
    
    
        merges.push(...getMerges(arr.length, newArr.length))
      } else {
    
    
        merges.push(...getMerges(arr.length, arr.length + newArr.length))
      }
      arr.push(...newArr)
    })
    return {
    
     arr, merges }
  }
  /*
  * 处理合并单元格参数merges
  * start 起始位置
  * end 结束位置
  * num 是要合并几列
  */
  function getMerges(start, end, num = 5) {
    
    
    let merges: any[] = []
    start += 1 //因为合并的时候要去除表头所以start要+1
    for (let index = 0; index < num; index++) {
    
    
      merges.push({
    
     s: {
    
     r: start, c: index }, e: {
    
     r: end, c: index } })
    }
    console.log(merges)
    return merges
  }

导出展示

在这里插入图片描述

结语

比较仓促的结束,因为要下班了,打工人从不加班哈哈哈哈

猜你喜欢

转载自blog.csdn.net/cha12138/article/details/130891257