Table export Excel in vue3

There is a high probability that Table tables are involved in the project, and there will be a need to export Excel. In the project, the xlsx plug-in is generally used to export

train of thought

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

install plugin

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' //Introduction to XLSX plug-in
import XLSXJSStyle from 'xlsx-js-style' //Customized XLSX style plug-in
import FileSaver from 'file-saver' //After adding styles, you need to use fileSaver everywhere (if You can directly use the export method of xlsx without using xlsx-js-style)

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

Get the data to be exported

I use antdv in my project, so I won’t show too much here

Write the export method

Our project requirements require merging cells, and the specific data format will be shown later

/**
 *
 * @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) {
    
    }
}

Process into the data desired by xlsx

Our data is a piece of data in which a certain field is in the form of an array, so when exporting, we need to split it into corresponding data according to this field, and then merge the repeated fields. I will take the fields in our project as an example, the data The format is as follows

 [
    {
    
    
      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
  }

export display

insert image description here

epilogue

It ended in a hurry, because it was time to get off work, and the workers never worked overtime hahahaha

Guess you like

Origin blog.csdn.net/cha12138/article/details/130891257