vue 前端生成 excel文件

594 阅读3分钟

vue 前端生成 excel文件 XLSX和 ExcelJS

待完善

日期,下拉(动态),表头颜色,合并单元格,日期 整型,字符串,小数保留几位,整数最大长度,各种校验,给第几个单元格设置颜色

表头数据


// 下载excel表头
export const sheetColumn = [
  {
    header: 'Id',
    key: 'Id',
    width: 10
  },
  {
    header: '日期',
    key: 'BillNo',
    width: 20, 
    style: { numFmt: 'dd/mm/yyyy' }
 
  },
  {
    header: '服务商',
    key: 'ServiceCode',
    width: 20, 
    style: { font: { name: 'Arial Black' } }
 
  },
  {
    header: '客户分组',
    key: 'CustomerGroupName',
    width: 10
  },
  {
    header: '运单号',
    key: 'ForecastNumber',
    width: 20
  },
  {
    header: '跟踪号',
    key: 'TrackingNumber',
    width: 20
  },
  {
    header: '客户单号',
    key: 'CustomerOrderNumber',
    width: 20
  },
  {
    header: '系统金额',
    key: 'SystemMoney',
    width: 10
  },
  {
    header: '*勘误费用项',
    key: 'ErrataFeeItemName',
    width: 20
  },
  {
    header: '*勘误金额',
    key: 'ErrataFee',
    width: 10
  },
  {
    header: '*勘误后总金额',
    key: 'ErrataTotalFee',
    width: 15
  },
  {
    header: '*勘误原因',
    key: 'Note',
    width: 20
  }
]

import XLSX from 'xlsx'


import XLSX from 'xlsx'
import { Trim } from '@/utils'

// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(sheet, sheetName) {
    sheetName = sheetName || 'sheet1'
    var workbook = {
        SheetNames: [sheetName],
        Sheets: {}
    }
    workbook.Sheets[sheetName] = sheet
        // 生成excel的配置项
    var wopts = {
        bookType: 'xlsx', // 要生成的文件类型
        bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
        type: 'binary'
    }
    var wbout = XLSX.write(workbook, wopts)
    var blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
        // 字符串转ArrayBuffer
    function s2ab(s) {
        var buf = new ArrayBuffer(s.length)
        var view = new Uint8Array(buf)
        for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
        return buf
    }
    return blob
}

function openDownloadDialog(url, saveName) {
    if (typeof url == 'object' && url instanceof Blob) {
        url = URL.createObjectURL(url) // 创建blob地址
    }
    var aLink = document.createElement('a')
    aLink.href = url
    aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
    var 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)
}

// 读取,修改,保存-导出
export function updateExcel(data, name) {
    // 格式
    // let aoa = [
    //   ['姓名', '性别', '年龄', '注册时间'],
    //   ['张三', '男', 18, new Date()]
    // ]
    let sheet = XLSX.utils.aoa_to_sheet(data)
    openDownloadDialog(sheet2blob(sheet), `${name}`)
}


 

import ExcelJS from 'exceljs'

import XLSX from 'xlsx'
import ExcelJS from 'exceljs'
import { Trim } from '@/utils'
import { sheetColumn } from '@/utils/excelHeader.js'
import lodash from 'lodash'


export const createExcelFileExcelJS = async (arr, fileName = `下载文件.xlsx`) => {

  // 组装数据
  let list = lodash.cloneDeep(arr || [])
  let sheetData = []
  for (let i = 0, len = list.length; i < len; i++) {
    let v = list[i]
    let obj = {
      Id: 1,
      BillNo: 2,
      ServiceCode: 3,
      CustomerGroupName: 4,
      ForecastNumber: 5,
      TrackingNumber: 6,
      CustomerOrderNumber: 7,
      SystemMoney: 8,
      ErrataFeeItemName: '',
      ErrataFee: '',
      ErrataTotalFee: '',
      ErrataNote: 9,
      items: `111`
    }
    sheetData.push(obj)
  }

  // 生成sheet
  const wb = new ExcelJS.Workbook()
  const sheet = wb.addWorksheet('Sheet1')
  sheet.columns = sheetColumn
   
/ 将第2行设置为 Comic Sans 字体。
sheet.getRow(2).font = {
    name: 'Comic Sans MS', family: 4, size: 16, underline: 'double', bold: true 
};
sheet.getCell('A1').font = {
  name: 'Comic Sans MS',
  family: 4,
  size: 16,
  underline: true,
  bold: true
};
 
// 垂直对齐
sheet.getCell('A3').font = {
  vertAlign: 'superscript'
};

 
// 在A2中填充深黄色格子和蓝色背景
sheet.getCell('A2').fill = {
  type: 'pattern',
  pattern:'darkTrellis',
  fgColor:{argb:'FFFFFF00'},
  bgColor:{argb:'FF0000FF'}
};
 
 

 
// 显示为“ 1.60%”
sheet.getCell('B1').value = 0.016;
sheet.getCell('B1').numFmt = '0.00%';

 

 

\
 
 
    // 将第3列设置为“货币格式”
    sheet.getColumn(3).numFmt = '"£"#,##0.00;[Red]-"£"#,##0.00';
 
  sheet.addRows(sheetData)
  for (let i = 0, len = sheetData.length; i < len; i++) {
    sheet.getCell(i + 1, 9).dataValidation = {
      type: 'list',
      formulae: ['"One,Two,Three,Four"']
    }
    
    / 指定单元格必须为非5的整数。
    // 向用户显示适当的错误消息(如果他们弄错了)
    sheet.getCell('A1').dataValidation = {
      type: 'whole',
      operator: 'notEqual',
      showErrorMessage: true,
      formulae: [5],
      errorStyle: 'error',
      errorTitle: 'Five',
      error: 'The value must not be Five'
    }; 
    
    // 指定单元格必须为1.5到7之间的十进制数字。
    // 添加“工具提示”以帮助指导用户
    sheet.getCell('A1').dataValidation = {
      type: 'decimal',
      operator: 'between',
      allowBlank: true,
      showInputMessage: true,
      formulae: [1.5, 7],
      promptTitle: 'Decimal',
      prompt: 'The value must between 1.5 and 7'
    };

    // 指定单元格的文本长度必须小于15
    sheet.getCell('A1').dataValidation = {
      type: 'textLength',
      operator: 'lessThan',
      showErrorMessage: true,
      allowBlank: true,
      formulae: [15]
    };

    // 指定单元格必须是2016年1月1日之前的日期
    sheet.getCell('A1').dataValidation = {
      type: 'date',
      operator: 'lessThan',
      showErrorMessage: true,
      allowBlank: true,
      formulae: [new Date(2016,0,1)]
    }; 
    
    
  }
  const buffer = await wb.xlsx.writeBuffer()
  var blob = new Blob([buffer], {
    type: 'application/octet-stream'
  })
  var url = blob
  if (typeof url == 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url) // 创建blob地址
  }
  var aLink = document.createElement('a')
  aLink.href = url
  aLink.download = fileName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
  var 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)
  return
}