vue+elementUI使用XLSX+xlsx-style 页面导出excel表格

安装和配置 xlsx 和 xlsx-style

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

安装启动时找不到 ./cptable 问题,需要在 vue.config.js 中 webpack 方法添加如下配置

chainWebpack(config) {
    // 配置信息
    config.externals({ './cptable': 'var cptable' })
}

vue页面导出

vue页面引用插件

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

给导出的table 设置id名,例如:id=“exportTable”

<el-button type="primary" @click="exportBtn">导出</el-button>
<el-table
    id="exportTable"
    ref="tableData"
    :data="tableData"
    border
    stripe
    style="width: 100%"
    max-height="700"
    highlight-current-row
  >
    <el-table-column prop="sno" label="学号" align="center" width="207" />
    <el-table-column prop="sname" label="姓名" align="center" width="207" />
    <el-table-column label="科目" align="center">
      <el-table-column prop="yuwen" label="语文" align="center" />
      <el-table-column prop="shuxuye" label="数学" align="center" />
      <el-table-column prop="waiyu" label="外语" align="center" />
    </el-table-column>
</el-table>

相关代码

    // 导出excel
    exportBtn() {
      // 使用 this.$nextTick 是在dom元素都渲染完成之后再执行
      this.$nextTick(function() {
        // 设置导出的内容是否只做解析,不进行格式转换false:要解析,true:不解析
        const xlsxParam = { raw: true }
        // 标记1-开始
        const wb = this.setExlStyle(
          XLSX.utils.table_to_book(
            document.querySelector('#exportTable'),
            xlsxParam
          )
        )
        // 标记1-结束
        
        this.addRangeBorder(
          wb['Sheets']['Sheet1']['!merges'],
          wb['Sheets']['Sheet1']
        )
        // 导出excel文件名
        const fileName = '学生成绩报表.xlsx'
        // 注意:导出Excel, 注意这里用到的是XLSXSTYLE对象  才会有设置的样式
        const wbout = XLSXSTYLE.write(wb, {
          bookType: 'xlsx', // 生成的文件类型
          bookSST: false,
          type: 'binary'
        })
        try {
          // 下载保存文件
          FileSaver.saveAs(
            new Blob([this.s2ab(wbout)], {
              type: 'application/octet-stream'
            }),
            fileName
          )
        } catch (e) {
          if (typeof console !== 'undefined') {
            console.log(e, wbout)
          }
        }
        return wbout
      })
    },
    // 设置表格样式
    setExlStyle(data) {
      const array = Object.keys(data.Sheets.Sheet1)
      array.forEach((key, index) => {
        // 设置每个单元格属性
        if (key.indexOf('!') < 0) {
          data.Sheets.Sheet1[key].s = {
            // 边框
            border: {
              top: { style: 'thin' },
              bottom: { style: 'thin' },
              left: { style: 'thin' },
              right: { style: 'thin' }
            },
            // 字体
            font: {
              sz: 12,
            },
            // 居中
            alignment: {
              horizontal: 'center',
              vertical: 'center',
              wrapText: true
            }
          }
        }
      })
      //标记2

      // 列宽
      data.Sheets.Sheet1['!cols'] = []
      // 行宽
      data.Sheets.Sheet1['!rows'] = []

      // 根据列数设置每一列的列宽  这里table有5列
      for (let i = 0; i < 6; i++) {
        data.Sheets.Sheet1['!cols'].push({ wpx: 80, wch: 20 })
      }
      //设置第一列
      data.Sheets.Sheet1['!cols'][0].wpx = 200
      return data
    },
    // 文件流转换
    s2ab(s) {
      // 如果存在ArrayBuffer对象(es6) 最好采用该对象
      if (typeof ArrayBuffer !== 'undefined') {
        // 1、创建一个字节长度为s.length的内存区域
        const buf = new ArrayBuffer(s.length)
        // 2、创建一个指向buf的Unit8视图,开始于字节0,直到缓冲区的末尾
        const view = new Uint8Array(buf)
        // 3、返回指定位置的字符的Unicode编码
        for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
        return buf
      } else {
        const buf = new Array(s.length)
        for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff
        return buf
      }
    },
    //表格边框:合并单元格时会丢失边框样式
    addRangeBorder(range, ws) {
      // s:起始位置,e:结束位置
      const arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
      range.forEach((item) => {
        const startRowNumber = Number(item.s.r)
        const startColumnNumber = Number(item.s.c)
        const endColumnNumber = Number(item.e.c)
        const endRowNumber = Number(item.e.r)
        // 合并单元格时会丢失边框样式,例如A1->A4 此时内容在A1 而range内获取到的是从0开始的,所以开始行数要+2
        for (let i = startColumnNumber; i <= endColumnNumber; i++) {
          for (let j = startRowNumber + 2; j <= endRowNumber + 1; j++) {
            ws[arr[i] + j] = {
              s: {
                border: {
                  top: { style: 'thin' },
                  left: { style: 'thin' },
                  bottom: { style: 'thin' },
                  right: { style: 'thin' }
                }
              }
            }
          }
        }
      })
      return ws
    },

vue页面效果和导出效果

在这里插入图片描述
在这里插入图片描述

问题1:导出的excel表格可以看到F列的1、2两行多出边框,解决方法

标记2 处增加下方代码,根据实际情况调整列名

// 导出的excel会给F这列两行有边框样式,手动去掉
var border = {
  top: { style: 'none' },
  bottom: { style: 'none' },
  left: { style: 'thin' },
  right: { style: 'none' }
}
data.Sheets.Sheet1['F1'].s = {
  border: border
}
data.Sheets.Sheet1['F2'].s = {}

问题2:el-table-column 标签 有 fixed 属性

表现为:vue页面展示正常,导出excel的数据出现重复,如下
在这里插入图片描述

解决方法:替换 标记1 处代码

// 有fixed情况
 const exportTable = document.getElementById('exportTable').cloneNode(true)
 exportTable.removeChild(exportTable.querySelector('.el-table__fixed'))
 // 调用改变样式的方法
 const wb = this.setExlStyle(
   XLSX.utils.table_to_book(
     exportTable,
     xlsxParam
   )
 )
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要修改导出Excel 表格的字体颜色,你可以使用 xlsx-style 库提供的 `XLSXStyle` 类的 `createStyle` 方法来创建自定义样式,然后将其应用到单元格中。 下面是一个使用 Vue 3 + TypeScript 和 xlsx-style-vite 库的示例代码: ```typescript <template> <div> <button @click="exportExcel">导出 Excel</button> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import { utils, writeFile } from 'xlsx-style-vite'; import { XLSXStyle } from 'xlsx-style-vite/xlsx-style'; export default defineComponent({ methods: { exportExcel() { const data = [ ['姓名', '年龄', '性别'], ['张三', 18, '男'], ['李四', 20, '女'], ['王五', 22, '男'] ]; const workbook = utils.book_new(); const worksheet = utils.aoa_to_sheet(data); // 创建自定义样式 const style = XLSXStyle.createStyle({ font: { color: '#FF0000' } }); // 将样式应用到单元格 utils.sheet_set_cell_style(worksheet, 'A1:C1', style); utils.book_append_sheet(workbook, worksheet, 'Sheet1'); writeFile(workbook, 'example.xlsx'); } } }); </script> ``` 在上面的代码中,我们首先创建了一个包含一些数据的数组 `data`。然后,我们使用 `utils.aoa_to_sheet` 方法将该数组转换为一个工作表对象。接着,我们使用 `XLSXStyle.createStyle` 方法创建了一个包含字体颜色为红色的自定义样式,并使用 `utils.sheet_set_cell_style` 方法将该样式应用到了表头行的所有单元格上。最后,我们将工作表对象添加到工作簿中,使用 `writeFile` 方法将工作簿导出为一个 Excel 文件。 需要注意的是,在使用 xlsx-style-vite 库时,要使用 `XLSXStyle` 类来创建自定义样式,这与原生的 xlsx-style 库有所不同,所以要引入 `xlsx-style-vite/xlsx-style` 模块。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值