安装和配置

EXCEL的安装

npm i xlsx
npm i xlsx-style

在项目中使用的版本分别是

"xlsx": "^0.18.5",
"xlsx-style": "^0.8.13"

EXCEL的使用

为了方便使用,我们封装了一个工具类,方便使用

创建工具文件

在utils文件夹下新建一个excel.js文件

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

export function createWs(data, fields, titles) {
  const ws = XLSX.utils.json_to_sheet(data, {
    header: fields
  })
  // 根据表头字段设置列宽
  const wsWidth = []
  // 全部默认宽度
  for (let i = 0; i < fields.length; i++) {
    wsWidth.push({
      wpx: 20
    })
  }

  // 设置表格的宽度
  ws['!cols'] = wsWidth

  const range = XLSX.utils.decode_range(ws['!ref'])

  // 设置表格样式
  for (let i = range.s.c; i < range.e.c + 1; i++) {
    for (let j = range.s.r; j < range.e.r + 1; j++) {
      // 单元格的地址, c是列,r是行, 如A1的地址是{c:0, r:0}
      const cell_address = {
        c: i,
        r: j
      }
      const column = XLSX.utils.encode_cell(cell_address)
      // 获取该单元格的值
      const value = ws[column].v
      ws[column].s = {
        // 单元格字体样式
        font: {
          name: '宋体',
          sz: 11,
        },
        // 单元格的边框线
        border: {
          color: {
            auto: 1
          },
          top: {
            style: 'thin'
          },
          bottom: {
            style: 'thin'
          },
          left: {
            style: 'thin'
          },
          right: {
            style: 'thin'
          }
        },
        // 单元格内容的排列方式
        alignment: {
          // 自动换行
          wrapText: 1,
          // 居中
          horizontal: 'center',
          vertical: 'center',
          indent: 0
        }
      }
    }
  }
  // 设置中文标题 因为后台返回的数据中属性只能以英文返回 所以需要转化为中文
  for (let c = range.s.c; c <= range.e.c; c++) {
    const header = XLSX.utils.encode_col(c) + '1'
    ws[header].v = titles[ws[header].v]
  }
  return ws
}

// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
export function sheet2blob(sheet, sheetName) {
  sheetName = sheetName || 'sheet1'
  const workbook = {
    SheetNames: [sheetName],
    Sheets: {}
  }
  workbook.Sheets[sheetName] = sheet // 生成excel的配置项

  // 下载这里一定要用 xlsx-style 的write() 方法才可以使导出excel表格带样式
  const wbout = XLSXStyle.write(workbook, {type: 'buffer'})
  // 字符串转ArrayBuffer
  return new Blob([wbout], {
    type: 'application/octet-stream'
  })
}

export function openDownloadDialog(url, saveName) {
  if (typeof url === 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url) // 创建blob地址
  }
  const aLink = document.createElement('a')
  aLink.href = url
  aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
  let event
  if (window.MouseEvent) event = new MouseEvent('click')
  else {
    event = document.createEvent('MouseEvents')
    event.initMouseEvent(
        'click',
        true,
        false,
        window,
        0,
        0,
        0,
        0,
        0,
        false,
        false,
        false,
        false,
        0,
        null
    )
  }
  aLink.dispatchEvent(event)
}

在项目中使用

// 引入Excel导出工具
import {createWs, openDownloadDialog, sheet2blob} from '@/utils/excel'

其中createWs方法是用来创建一个sheet表格,接收三个参数,第一个参数是数据,第二个参数是表头字段,第三个参数是表头中文名,示例代码如下

假设我们有一个数据,该数据是一个数组,数组中的每一项是一个对象,对象中的属性是表头字段,属性值是表头中文名

// 整理成表格数据
const data = this.scoreData.map((item, index) => {
  return {
    index: index + 1,
    name: item.name,
    chinese: item.chinese || 0,
    mathematics: item.mathematics || 0,
    english: item.english || 0,
    physics: item.physics || 0,
    chemistry: item.chemistry || 0,
    biology: item.biology || 0,
    politics: item.politics || 0,
    history: item.history || 0,
    geography: item.geography || 0,
    total: item.total || 0,
    average: item.average || 0
  }
})

其中,数据对应的表头字段如下

const fields = [
  'index',
  'name',
  'chinese',
  'mathematics',
  'english',
  'physics',
  'chemistry',
  'biology',
  'politics',
  'history',
  'geography',
  'total',
  'average'
]

表头中文名如下

const titles = {
  index: '序号',
  name: '姓名',
  chinese: '语文',
  mathematics: '数学',
  english: '英语',
  physics: '物理',
  chemistry: '化学',
  biology: '生物',
  politics: '政治',
  history: '历史',
  geography: '地理',
  total: '总分',
  average: '平均分'
}

最后,我们调用createWs方法,将数据,表头字段,表头中文名传入,得到一个sheet表格,然后调用sheet2blob方法,将sheet表格转成blob对象,最后调用openDownloadDialog方法,将blob对象传入,即可实现导出excel表格的功能

const ws = createWs(data, fields, title)
openDownloadDialog(sheet2blob(ws), '某班-成绩表.xlsx')

进阶使用

  1. 在excel.js中,可以设置表头的宽度,如:
// 设置表头的宽度
// 成绩 设置列宽
fields.forEach((item) => {
  if (item === 'index') {
    wsWidth.push({wpx: 65})
  } else if (item === 'name') {
    wsWidth.push({wpx: 100})
  } else {
    wsWidth.push({wpx: 65})
  }
})

这样的话成绩的序号(index)列宽度为65px,姓名(name)列宽度为100px,其他列宽度为65px 效果如下: 成绩导出效果图 2. 也可以设置单元格字体的样式,如:

// 单元格字体样式
  font: {
    name: '宋体',
    // 字体大小
    sz: 11,
    // 字体颜色
    color: {
      rgb: value === '红码' || value === '阳性!' ? 'FF0000' : value === '绿码' || value === '阴性' || value === '已采样' ? '008000' : value === '黄码' ? 'FFA500' : '000000'
    },
    // 健康码 行程码 检测结果 字体加粗
    bold: value === '红码' || value === '绿码' || value === '黄码' || value === '阴性' || value === '阳性!' || value === '已采样' || value === '检测结果'
  }

这样的话,在前面的表头宽度设置对应数值之后,健康码、行程码、检测结果这三列的字体颜色就会根据值的不同而不同,效果如下: 健康码导出效果图

Last Updated:
Contributors: 黄定鑫