vue:功能【xlsx】纯前端导出Excel

一、安装插件

npm i -S file-saver xlsx
npm i -D script-loader

二、引入

import FileSaver from "file-saver";
import XLSX from "xlsx";

三、封装的代码

注:生成的excel封装的方法如下(支持表头合并、导出的 excel 支持生成多个sheet工作表、表格可自适应宽度、自适应高度、合并表格)

【步骤】

1、导出操作涉及到使用 OutExcelSheet.exportSheetExcel 函数来导出一个名为 karlaExport导出.xlsx 的 Excel 文件。【三个参数:sheetData、mergesHeader 和文件名】

2、sheetData 是一个数组,用于存储要导出的表格数据。在代码中,使用了一个名为 sheet1 的对象来定义表格的名称、数据、合并单元格和行高等信息。

3、mergesHeader 是一个数组,用于指定要合并的行和列的范围。在给定的代码中,合并了一些特定的行和列,以创建标题行和表头的合并效果。

4、最后,通过调用 OutExcelSheet.exportSheetExcel 函数,并传递以上参数,将生成的 Excel 文件导出到本地。

import XLSX from 'xlsx-js-style'
import FileSaver from 'file-saver'

export default {
  exportSheetExcel(sheetData, mergerArr, fileName = 'karlaExport.xlsx') {
    const wb = XLSX.utils.book_new() // 创建一个新工作簿

    for (let i = 0; i < sheetData.length; i++) {
      const sheet = sheetData[i]

      // 检查数据项是否存在
      if (!sheet.data) {
        continue // 如果数据项不存在,则跳过当前循环
      }

      const ws = XLSX.utils.aoa_to_sheet(sheet.data) // 将数据数组转换为工作表

      // 设置合并单元格
      ws['!merges'] = sheet.merges && sheet.merges.length > 0 ? [...sheet.merges, ...(mergerArr || [])] : mergerArr;

      // 设置列宽为自适应
      if (sheet.data.length > 0) {
        ws['!cols'] = sheet.data[0].map((_, index) => ({ wch: 15 }))
      }

      // 设置行高
      if (sheet.rowHeights && sheet.rowHeights.length > 0) {
        ws['!rows'] = sheet.rowHeights.map((height) => ({ hpt: height, hpx: height }))
      }

      const borderAll = {
        top: { style: 'thin' },
        bottom: { style: 'thin' },
        left: { style: 'thin' },
        right: { style: 'thin' }
      }

      // 设置单元格样式
      for (const key in ws) {
        if (ws.hasOwnProperty(key)) {
          const cell = ws[key]
          if (typeof cell === 'object') {
            cell.s = {
              border: borderAll,
              alignment: {
                horizontal: 'center',
                vertical: 'center',
                wrapText: true
              },
              font: {
                sz: 12,
                color: {
                  rgb: '000000'
                }
              },
              numFmt: 'General',
              fill: {
                fgColor: { rgb: 'FFFFFF' }
              }
            }
          }
        }
      }

      XLSX.utils.book_append_sheet(wb, ws, sheet.name) // 将工作表添加到工作簿并指定名称
    }

    const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) // 将工作簿转换为数组

    const file = new Blob([wbout], { type: 'application/octet-stream' }) // 创建Blob对象
    FileSaver.saveAs(file, fileName) // 下载文件
  },
  // 二维数组中空的数据设置为 0【数据处理】
  emptyValues(array, defaultValue) {
    for (let i = 0; i < array.length; i++) {
      for (let j = 0; j < array[i].length; j++) {
        if (array[i][j] === null || array[i][j] === undefined || array[i][j] === '') {
          array[i][j] = defaultValue
        }
      }
    }
    return array
  },
  // 生成excel列表数据【格式转换】
  handleExcelTable(columnHeader, list) {
    if (list.length === 0) return []

    // 表头
    const tableColumn = Object.keys([columnHeader][0])

    // 表格生成的数据
    const sheet = [tableColumn]
    list.forEach((item) => {
      const row = tableColumn.map((column) => item[column])
      sheet.push(row)
    })

    // 表头匹配对应的中文
    const firstRow = sheet[0].map((column) => columnHeader[column])
    sheet[0] = firstRow

    return sheet || []
  }
}

调用方法

// 参数:sheetData:转换后的二维数组、mergesHeader:需要合并的数据、表名
OutExcelSheet.exportSheetExcel(sheetData, mergesHeader, `LeavePay导出.xlsx`)

二、设置最后一条数据无框

  exportSheetExcel(sheetData, mergerArr, fileName = 'karlaExport.xlsx') {
    const wb = XLSX.utils.book_new() // 创建一个新工作簿

    for (let i = 0; i < sheetData.length; i++) {
      const sheet = sheetData[i]

      // 检查数据项是否存在
      if (!sheet.data) {
        continue // 如果数据项不存在,则跳过当前循环
      }

      const ws = XLSX.utils.aoa_to_sheet(sheet.data) // 将数据数组转换为工作表

      // 设置合并单元格
      ws['!merges'] = sheet.merges && sheet.merges.length > 0 ? [...sheet.merges, ...(mergerArr || [])] : mergerArr;     

      // 设置列宽为自适应
      if (sheet.data.length > 0) {
        ws['!cols'] = sheet.data[0].map((_, index) => ({ wch: 15 }))
      }

      // 设置行高
      if (sheet.rowHeights && sheet.rowHeights.length > 0) {
        ws['!rows'] = sheet.rowHeights.map((height) => ({ hpt: height, hpx: height }))
      }

      const borderAll = {
        top: { style: 'thin' },
        bottom: { style: 'thin' },
        left: { style: 'thin' },
        right: { style: 'thin' }
      }

      // 设置单元格样式
      for (const key in ws) {
        if (ws.hasOwnProperty(key)) {
          const cell = ws[key]
          if (typeof cell === 'object') {
            // 判断是否为最后一行【核心】
            const rowIndex = parseInt(key.replace(/[A-Z]/g, ''))
            if (rowIndex === sheet.data.length) {
              if (cell.s && cell.s.border) {
                delete cell.s.border.right // 删除右侧边框样式
              }
              // 内容居中
              cell.s = cell.s || {}
              cell.s.alignment = cell.s.alignment || {}
              cell.s.alignment.horizontal = 'center'
              cell.s.alignment.vertical = 'center'
              cell.s.alignment.wrapText = true
            } else {
              cell.s = {
                border: borderAll,
                alignment: {
                  horizontal: 'center',
                  vertical: 'center',
                  wrapText: true
                },
                font: {
                  sz: 12,
                  color: {
                    rgb: '000000'
                  }
                },
                numFmt: 'General',
                fill: {
                  fgColor: { rgb: 'FFFFFF' }
                }
              }
            }
          }
        }
      }

      XLSX.utils.book_append_sheet(wb, ws, sheet.name) // 将工作表添加到工作簿并指定名称
    }

    const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) // 将工作簿转换为数组

    const file = new Blob([wbout], { type: 'application/octet-stream' }) // 创建Blob对象
    FileSaver.saveAs(file, fileName) // 下载文件
  },

把条件合并到封装方法中

  exportSheetExcel(sheetData, mergerArr, fileName = 'karlaExport.xlsx', statusBorder = false) {
    const wb = XLSX.utils.book_new() // 创建一个新工作簿

    for (let i = 0; i < sheetData.length; i++) {
      const sheet = sheetData[i]

      // 检查数据项是否存在
      if (!sheet.data) {
        continue // 如果数据项不存在,则跳过当前循环
      }

      const ws = XLSX.utils.aoa_to_sheet(sheet.data) // 将数据数组转换为工作表

      // 设置合并单元格
      ws['!merges'] = sheet.merges && sheet.merges.length > 0 ? [...sheet.merges, ...(mergerArr || [])] : mergerArr;

      // 设置列宽为自适应
      if (sheet.data.length > 0) {
        ws['!cols'] = sheet.data[0].map((_, index) => ({ wch: 15 }))
      }

      // 设置行高
      if (sheet.rowHeights && sheet.rowHeights.length > 0) {
        ws['!rows'] = sheet.rowHeights.map((height) => ({ hpt: height, hpx: height }))
      }

      const borderAll = {
        top: { style: 'thin' },
        bottom: { style: 'thin' },
        left: { style: 'thin' },
        right: { style: 'thin' }
      }

      // 设置单元格样式
      for (const key in ws) {
        if (ws.hasOwnProperty(key)) {
          const cell = ws[key]
          if (cell && typeof cell === 'object') {
            // 判断是否为最后一行【核心】
            const rowIndex = parseInt(key.replace(/[A-Z]/g, ''))
            if (statusBorder && rowIndex === sheet.data.length) {
              if (cell.s && cell.s.border) {
                delete cell.s.border.right // 删除右侧边框样式
              }
              // 内容居中
              cell.s = cell.s || {}
              cell.s.alignment = cell.s.alignment || {}
              cell.s.alignment.horizontal = 'center'
              cell.s.alignment.vertical = 'center'
              cell.s.alignment.wrapText = true
            } else {
              cell.s = {
                border: borderAll,
                alignment: {
                  horizontal: 'center',
                  vertical: 'center',
                  wrapText: true
                },
                font: {
                  sz: 12,
                  color: {
                    rgb: '000000'
                  }
                },
                numFmt: 'General',
                fill: {
                  fgColor: { rgb: 'FFFFFF' }
                }
              }
            }
          }
        }
      }

      XLSX.utils.book_append_sheet(wb, ws, sheet.name) // 将工作表添加到工作簿并指定名称
    }

    const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }) // 将工作簿转换为数组

    const file = new Blob([wbout], { type: 'application/octet-stream' }) // 创建Blob对象
    FileSaver.saveAs(file, fileName) // 下载文件
  },

相关推荐

  1. vue功能xlsx前端导出Excel

    2024-03-15 07:32:03       24 阅读
  2. 前端导出Excel

    2024-03-15 07:32:03       21 阅读
  3. 前端实现导出xlsx功能

    2024-03-15 07:32:03       20 阅读
  4. 前端导出,设置导出xlsx文件样式xlsx-js-style

    2024-03-15 07:32:03       39 阅读
  5. Vue 导出前端数据报表为xlsx文件

    2024-03-15 07:32:03       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-15 07:32:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-15 07:32:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-15 07:32:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-15 07:32:03       20 阅读

热门阅读

  1. 每日一题 第三期 洛谷 国王游戏

    2024-03-15 07:32:03       19 阅读
  2. 2062:【例1.3】电影票

    2024-03-15 07:32:03       20 阅读
  3. 基于单片机的步进电机升降速并行控制

    2024-03-15 07:32:03       17 阅读
  4. 有密码pdf保存为无密码的

    2024-03-15 07:32:03       18 阅读
  5. C# 中的 List<int> 和 int[] ?

    2024-03-15 07:32:03       21 阅读
  6. GO sync.pool学习笔记

    2024-03-15 07:32:03       18 阅读
  7. MyBatis 之三:配置文件详解和 Mapper 接口方式

    2024-03-15 07:32:03       19 阅读
  8. 【图解物联网】第零章 前言

    2024-03-15 07:32:03       21 阅读