vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue exceljs导出excel

Vue纯前端使用exceljs导出excel文件的完整图文教程

作者:Alex_001

这篇文章将一步一步为大家详细介绍一下exceljs插件中的使用,以及如何使用exceljs导出excel文件,感兴趣的小伙伴可以跟随小编一起学习一下

一.导出数据为xlsx表格文件 表格带下拉选择

1.npm引入

npm install exceljs@4.3.0

2.cnpm引入(npm引入失败的话)

cnpm install exceljs@4.3.0

3.页面引入方式  import ExcelJS from "exceljs";

二、实例1

<template>
  <button @click="exportExcel">导出Excel</button>
</template>

<script>
import ExcelJS from "exceljs";

export default {
  methods: {
    async exportExcel() {
      const workbook = new ExcelJS.Workbook();
      // 创建一个工作表 elecel里面可以有多个工作表
      const worksheet = workbook.addWorksheet("Sheet1");

      // 设置创建的工作表的表头
      worksheet.getCell("A1").value = "姓名";
      worksheet.getCell("B1").value = "年龄";
      worksheet.getCell("C1").value = "性别";
      worksheet.getCell("D1").value = "来源";

      // 添加数据行 一般用于循环我们后端传来的数据设置导出的每一行
      worksheet.addRow(["Alex", 25, "男", "微信"]);
      worksheet.addRow(["Alix", 30, "女", "微信"]);
      worksheet.addRow(["Andy", 35, "男", "微信"]);

      // 设置设置我们的下拉选项的数据列表
      const dropdownOptions = ["男", "女"];
      const dropdownOptions1 = ["微信", "支付宝", "云闪付"];

      // 创建我们的第二个工作表用于存放我们下拉菜单的选项
      const worksheet2 = workbook.addWorksheet("sheet2");


      // 这里设置的是第二个工作表一列一列的展示 看图2
      worksheet2.getColumn("A").values = dropdownOptions
      worksheet2.getColumn("B").values = dropdownOptions1


      // 这里设置的是第二个工作表一行一行的展示 看图3
      // worksheet2.addRow(dropdownOptions);
      // worksheet2.addRow(dropdownOptions1);
       
      // 注意:-------------解释
      // 如果是一行一行的 我们的sheet 的c列关联sheet2的第一行数据的话就要这样写
      //  formulae: [`=sheet2!$A$1:$Z$1`],
      // 第二行就要这样写formulae: [`=sheet2!$A$2:$Z$2`]但是这样的和 他只会写到第二行的A-Z

      // 如果一列一列的话 我们的sheet 的c列关联sheet2的第一列数据的话就要这样写
      //  formulae: [`=sheet2!$A:$A`],
      // 如果关联到第二列就要这样写  formulae: [`=sheet2!$B:$B`],



      // 性别下拉  这是用来把工作表1中的某一列关联到工作表二中的某一行作为下拉框的值或者是某一列
      const col = worksheet.getColumn("C");
      // 遍历此列中的所有当前单元格,包括空单元格
      col.eachCell({ includeEmpty: true }, function (cell, rowNumber) {
        // 设置下拉列表
        cell.dataValidation = {
          type: "list",
          allowBlank: true,
          formulae: [`=sheet2!$A:$A`], //行取值
          // formulae: [`=sheet2!$A$1:$Z$1`], //列取值
        };
      });

      //来源下拉
      const col3 = worksheet.getColumn("D");
      // 遍历此列中的所有当前单元格,包括空单元格
      col3.eachCell({ includeEmpty: true }, function (cell, rowNumber) {
        // 设置下拉列表
        cell.dataValidation = {
          type: "list",
          allowBlank: true,
          formulae: [`=sheet2!$B:$B`],//行取值
          // formulae: [`=sheet2!$A$2:$Z$2`],//列取值
        };
      });

      // 导出Excel文件
      const buffer = await workbook.xlsx.writeBuffer();
      const blob = new Blob([buffer], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      });
      const url = URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "data.xlsx";
      link.click();
      URL.revokeObjectURL(url);
    },
  },
};
</script>

三、实例2-动态数据

// 引入格式化工具类
import {timestampToDay, timestampToTime} from '@/utils/util.js'
export default {
  props: {
    exportExcelArray: {
      type: Array,
      default: () => {
            return []
          }
    },
    tableData: {
      type: Array,
      default: () => {
            return []
          }
    },
    // 导出自定义字体颜色所属字段
    showRedList: {
      type: Array,
      default: () => {
        return ['未通过', '否']
      }
    },
    showOrangeList: {
      type: Array,
      default: () => {
        return ['未测试']
      }
    },
    showGreenList: {
      type: Array,
      default: () => {
        return ['通过', '是']
      }
    },
    // 导出自定义字体颜色
    customColor: {
      type: String,
      default: 'D63640'
    },
    customGreen: {
      type: String,
      default: '1AD96F'
    },
    customOrange: {
      type: String,
      default: 'f2b400'
    },
    // 是否显示多个工作表-带下拉框表格
    showMultipleMenu: {
      type: Boolean,
      default: false
    },
    // 是否显示多个工作表-独立
    showMultiple: {
      type: Boolean,
      default: false
    },
  },
  methods: {
    //表格formatter数据格式化
    formatter (value,item,row,prop) {
      // console.log('value',value)
      // console.log('item',item)
      // console.log('row',row)
      // console.log('prop',prop)
      //针对table中item多层对象层级的情况
      if(prop.indexOf('.') > 0){
        let temp = prop.split('.')
        // console.log('temp',temp)
        //item中嵌套两层(列表数组)
        if(temp.length == 2){
          let temp = prop.split('.')
          let arry = row[temp[0]]
          let result = ''
          // 多层对象层级的情况是否为数组
          if(Array.isArray(arry)){
            for(let i in arry){
              // console.log('arry[i][temp[1]]',arry[i][temp[1]])
              if(!this.isNull(arry[i][temp[1]])){
                if(item.formatterType == 'common-type'){  //通用类型转换
                  result = arry[i][temp[1]]
                } else if(item.formatterType == 'time-type'){ //时间标准格式化
                  if(item.timestampToDay){
                    result = timestampToDay(arry[i][temp[1]])
                  }else {
                    result = timestampToTime(arry[i][temp[1]])
                  }
                } else if(item.formatterType == 'amount-type'){ //金额转换
                  result = (arry[i][temp[1]] / 100).toFixed(2)
                } else {
                  result = arry[i][temp[1]]
                }
                return result
              }
            }
          }else{
            // 多层对象层级的情况是否为对象
            if(!this.isNull(row[temp[0]][temp[1]])){
              if(item.formatterType == 'common-type'){  //通用类型转换
                result = row[temp[0]][temp[1]]
              } else if(item.formatterType == 'time-type'){ //时间标准格式化
                if(item.timestampToDay){
                  result = timestampToDay(row[temp[0]][temp[1]])
                }else {
                  result = timestampToTime(row[temp[0]][temp[1]])
                }
              } else if(item.formatterType == 'amount-type'){ //金额转换
                result = (row[temp[0]][temp[1]] / 100).toFixed(2)
              } else {
                result = row[temp[0]][temp[1]]
              }
              return result
            }
          }
        }
      } else{ //item中无嵌套对象
        let temp = prop.split('.')
        if(item.formatterType == 'common-type'){  //通用类型转换
          let arry = item.formatterInfo
          for(let i in arry){
            if(arry[i].value == value){
              return arry[i].label
            }
          }
        } else if(item.formatterType == 'time-type'){ //时间标准格式化
          // console.log('row[temp[0]])1',row[temp[0]])
          if(!this.isNull(row[temp[0]])){
            // return value.substring(0,value.length - 2)
            if(item.timestampToDay){
              return timestampToDay(value)
            }else {
              return timestampToTime(value)
            }
          }
        } else if(item.formatterType == 'amount-type'){ //金额转换
          return (value / 100).toFixed(2)
        } else {
          return value
        }
      }
    },
    // 是否显示多个工作表
    async exportExcelMultiple() {
      const vm = this
      let workbook = new ExcelJS.Workbook();
      // 是否显示多个工作表-独立
      if(vm.showMultiple){
        let workbookList = [
          {
            "sheetName": '质检列表',
            worksheetData: this.tableData, // 接口导出数据
            worksheetHeaderList: this.exportExcelArray // excel顶部标题自定义
          }
        ]

        workbook = await this.exportExcelMultipleEach(workbook,workbookList);

      }else {

        // 创建一个工作表 elecel里面可以有多个工作表
        const worksheet = workbook.addWorksheet("Sheet1");

        // 设置创建的工作表的表头
        // 表头对象-标题超过26个字母则继续添加
        let topCellObj = {
          1: 'A',
          2: 'B',
          3: 'C',
          4: 'D',
          5: 'E',
          6: 'F',
          7: 'G',
          8: 'H',
          9: 'I',
          10: 'J',
          11: 'K',
          12: 'L',
          13: 'M',
          14: 'N',
          15: 'O',
          16: 'P',
          17: 'Q',
          18: 'R',
          19: 'S',
          20: 'T',
          21: 'U',
          22: 'V',
          23: 'W',
          24: 'S',
          25: 'Y',
          26: 'Z',
        }
        this.exportExcelArray.forEach((item,index)=>{
          for(let path in topCellObj){
            if(path == index + 1){
              // 标头标题赋值
              worksheet.getCell(topCellObj[path]+"1").value = item.label;
              break
            }
          }
        })

        // 添加数据行 一般用于循环我们后端传来的数据设置导出的每一行
        this.tableData.forEach((row)=> {
          let arr = []
          for (const [key, value] of Object.entries(row)) {
            // console.log(`Key: ${key}, Value: ${value}`);
            for (let i=0; i < this.exportExcelArray.length; i++) {
              let item = this.exportExcelArray[i]
              if (item.prop == key) {
                // 格式化字段
                let formatterValue = this.formatter(row[item.prop],item,row,item.prop)
                arr = [...arr, ...[{index:i,value: formatterValue ? formatterValue : value}]]
                break
              }
            }
          }
          // index排序并且返回value字段
          const arrNew = arr.sort((a, b) => a.index - b.index).map(item => item.value);
          worksheet.addRow(arrNew);
        })
        // return

        // 添加列标题并定义列键和宽度
        // 注意:这些列结构仅是构建工作簿的方便之处,除了列宽之外,它们不会完全保留。
        worksheet.columns = this.exportExcelArray.map((item)=>{
          return {
            header: item.label,
            key: item.prop,
            width: item.width,
          }
        })

        // 设置第一行表头背景色和字体颜色
        worksheet.getRow(1).eachCell({ includeEmpty: true }, (cell, colNumber) => {
          cell.fill = {
            type: 'pattern',
            pattern: 'solid',
            // fgColor: { argb: (colNumber === 1 || colNumber === 2) ? 'FF79bbff' : 'FF95d475' }
            fgColor: { argb: 'FF79bbff' }
          };
          cell.font = {
            size: 10,
            color: { argb: 'FFFFFFFF' } // 白色
          };
          cell.alignment = {
            horizontal: "center",// 水平居中
            vertical: 'middle', // 垂直居中
          }
        });

        // 添加边框+水平+垂直居中
        for (let num = 0; num < worksheet.lastRow._number; num++) {
          // 循环出每一行
          for (let index = 0; index < worksheet.columns.length; index++) {
            let rowCell = worksheet.getRow(num + 1).getCell(index + 1)
            // console.log('rowCell',rowCell)
            // 表格的值包含于颜色列表内则给单元格赋值颜色样式
            if(rowCell&&rowCell._value&&rowCell._value.model&&rowCell._value.model.value&&num>0){
              const colValue = rowCell._value.model.value
              // 自定义字体颜色
              let col = '000000'
              // 红色
              if(vm.showRedList.includes(colValue)){
                col = vm.customColor
              }
              //绿色
              if(vm.showGreenList.includes(colValue)){
                col = vm.customGreen
              }
              // 橙色
              if(vm.showOrangeList.includes(colValue)){
                col = vm.customOrange
              }
              // 字体
              rowCell.font = {
                size: 10,
                // 自定义字体颜色
                color: {argb: col},
              }
            }

            // 循环出每一个单元格
            rowCell.border = {
              // 为单元格添加边框
              top: { style: "thin" },
              left: { style: "thin" },
              bottom: { style: "thin" },
              right: { style: "thin" },
            };
            rowCell.alignment = {
              // 为单元格添加水平+垂直居中
              horizontal: "center",// 水平居中
              vertical: 'middle', // 垂直居中
            };
          }
        }

        // 设置设置我们的下拉选项的数据列表
        const dropdownOptions = ["吉祥星", "纳斯达", "普耐尔", "阿龙"];
        const dropdownOptions1 = ["自研", "英卡", "微步", "茂现", "文泰"];

        // 创建我们的第二个工作表用于存放我们下拉菜单的选项
        const worksheet2 = workbook.addWorksheet("sheet2");


        // 这里设置的是第二个工作表一列一列的展示 看图2
        worksheet2.getColumn("A").values = dropdownOptions
        worksheet2.getColumn("B").values = dropdownOptions1


        // 这里设置的是第二个工作表一行一行的展示 看图3
        // worksheet2.addRow(dropdownOptions);
        // worksheet2.addRow(dropdownOptions1);

        // 注意:-------------解释
        // 如果是一行一行的 我们的sheet 的c列关联sheet2的第一行数据的话就要这样写
        //  formulae: [`=sheet2!$A$1:$Z$1`],
        // 第二行就要这样写formulae: [`=sheet2!$A$2:$Z$2`]但是这样的和 他只会写到第二行的A-Z

        // 如果一列一列的话 我们的sheet 的c列关联sheet2的第一列数据的话就要这样写
        //  formulae: [`=sheet2!$A:$A`],
        // 如果关联到第二列就要这样写  formulae: [`=sheet2!$B:$B`],

        // 性别下拉  这是用来把工作表1中的某一列关联到工作表二中的某一行作为下拉框的值或者是某一列
        const col = worksheet.getColumn("F");
        // 遍历此列中的所有当前单元格,包括空单元格
        col.eachCell({ includeEmpty: true }, function (cell, rowNumber) {
          // 设置下拉列表
          cell.dataValidation = {
            type: "list",
            allowBlank: true,
            formulae: [`=sheet2!$A:$A`], //行取值
            // formulae: [`=sheet2!$A$1:$Z$1`], //列取值
          };
        });

        //来源下拉
        const col3 = worksheet.getColumn("G");
        // 遍历此列中的所有当前单元格,包括空单元格
        col3.eachCell({ includeEmpty: true }, function (cell, rowNumber) {
          // 设置下拉列表
          cell.dataValidation = {
            type: "list",
            allowBlank: true,
            formulae: [`=sheet2!$B:$B`],//行取值
            // formulae: [`=sheet2!$A$2:$Z$2`],//列取值
          };
        });

      }


      // 导出Excel文件
      const buffer = await workbook.xlsx.writeBuffer();
      const blob = new Blob([buffer], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      });
      const url = URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "质检列表记录.xlsx";
      link.click();
      URL.revokeObjectURL(url);
    },
    // workbook:新建表单
    // workbook-sheetName: 表格名称,
    // workbook-worksheetData: 表格数据,
    // workbook-worksheetHeaderList: 表格顶部标题
    // workbookList: 导出列表+表头
    async exportExcelMultipleEach(workbook,workbookList) {
      const vm = this
      workbookList.forEach((mItem,index)=>{
        // 创建一个工作表 elecel里面可以有多个工作表
        const worksheet = workbook.addWorksheet(mItem&&mItem.sheetName ? mItem.sheetName : "Sheet"+(index+1));

        // 设置创建的工作表的表头
        // 表头对象-标题超过26个字母则继续添加
        let topCellObj = {
          1: 'A',
          2: 'B',
          3: 'C',
          4: 'D',
          5: 'E',
          6: 'F',
          7: 'G',
          8: 'H',
          9: 'I',
          10: 'J',
          11: 'K',
          12: 'L',
          13: 'M',
          14: 'N',
          15: 'O',
          16: 'P',
          17: 'Q',
          18: 'R',
          19: 'S',
          20: 'T',
          21: 'U',
          22: 'V',
          23: 'W',
          24: 'S',
          25: 'Y',
          26: 'Z',
        }
        mItem.worksheetHeaderList.forEach((item,index)=>{
          for(let path in topCellObj){
            if(path == index + 1){
              worksheet.getCell(topCellObj[path]+"1").value = item.label;
              break
            }
          }
        })

        // 添加数据行 一般用于循环我们后端传来的数据设置导出的每一行
        mItem.worksheetData.forEach((row)=> {
          let arr = []
          for (const [key, value] of Object.entries(row)) {
            // console.log(`Key: ${key}, Value: ${value}`);
            for (let i=0; i < mItem.worksheetHeaderList.length; i++) {
              let item = mItem.worksheetHeaderList[i]
              if (item.prop == key) {
                // 格式化字段
                let formatterValue = this.formatter(row[item.prop],item,row,item.prop)
                arr = [...arr, ...[{index:i,value: formatterValue ? formatterValue : value}]]
                break
              }
            }
          }
          // index排序并且返回value字段
          const arrNew = arr.sort((a, b) => a.index - b.index).map(item => item.value);
          worksheet.addRow(arrNew);
        })
        // return

        // 添加列标题并定义列键和宽度
        // 注意:这些列结构仅是构建工作簿的方便之处,除了列宽之外,它们不会完全保留。
        worksheet.columns = mItem.worksheetHeaderList.map((item)=>{
          return {
            header: item.label,
            key: item.prop,
            width: item.width,
          }
        })

        // 设置第一行表头背景色和字体颜色
        worksheet.getRow(1).eachCell({ includeEmpty: true }, (cell, colNumber) => {
          cell.fill = {
            type: 'pattern',
            pattern: 'solid',
            // fgColor: { argb: (colNumber === 1 || colNumber === 2) ? 'FF79bbff' : 'FF95d475' }
            fgColor: { argb: 'FF79bbff' }
          };
          cell.font = {
            size: 10,
            color: { argb: 'FFFFFFFF' } // 白色
          };
          cell.alignment = {
            horizontal: "center",// 水平居中
            vertical: 'middle', // 垂直居中
          }
        });

        // 添加边框+水平+垂直居中
        for (let num = 0; num < worksheet.lastRow._number; num++) {
          // 循环出每一行
          for (let index = 0; index < worksheet.columns.length; index++) {
            let rowCell = worksheet.getRow(num + 1).getCell(index + 1)
            // console.log('rowCell',rowCell)
            // 表格的值包含于颜色列表内则给单元格赋值颜色样式
            if(rowCell&&rowCell._value&&rowCell._value.model&&rowCell._value.model.value&&num>0){
              const colValue = rowCell._value.model.value
              // 自定义字体颜色
              let col = '000000'
              // 红色
              if(vm.showRedList.includes(colValue)){
                col = vm.customColor
              }
              //绿色
              if(vm.showGreenList.includes(colValue)){
                col = vm.customGreen
              }
              // 橙色
              if(vm.showOrangeList.includes(colValue)){
                col = vm.customOrange
              }
              // 字体
              rowCell.font = {
                size: 10,
                // 自定义字体颜色
                color: {argb: col},
              }
            }

            // 循环出每一个单元格
            rowCell.border = {
              // 为单元格添加边框
              top: { style: "thin" },
              left: { style: "thin" },
              bottom: { style: "thin" },
              right: { style: "thin" },
            };
            rowCell.alignment = {
              // 为单元格添加水平+垂直居中
              horizontal: "center",// 水平居中
              vertical: 'middle', // 垂直居中
            };
          }
        }

      })

      return workbook
    },
  }
}

3.1 exportExcelArray格式

exportExcelArray: [
  {
    prop: 'serialNumber', // 字段key
    label: '序号', // 字段名称
    formatterFlag: false,  // 值是否需要格式化
    align: 'center',  // 布局-居中
    width: 10,  // 列宽度
  },
  {
    prop: 'createTime',
    label: '创建时间',
    formatterFlag: true,
    formatterType: 'time-type', // 时间校验-时间戳转为日期
  },
]

3.2 @/utils/util.js

/**
 * 时间戳
 * @param {*} timestamp  时间戳
 */
 
//尾部补零(常用13为时间戳字符串,后端返回格式不一定是13位)
const padEndFun = (val,digit,num) => {
  if(val == '' || val == undefined || val == null){
    return ''
  }
  if(typeof val == 'number'){
    val = val.toString()
  }
  // console.log('val',val)
  let str = val.padEnd(digit, num.toString())
  return Number(str)
},

const timestampToTime = (timestamp) => {
    if(timestamp == '' || timestamp == undefined || timestamp == null){
      return ''
    }
    if(padEndFun){
      //时间戳为10位需*1000,时间戳为13位的话不需乘1000
      timestamp = padEndFun(timestamp,13,0)
    }
    let date = new Date(timestamp) //时间戳为10位需*1000,时间戳为13位的话不需乘1000
    let Y = date.getFullYear() + '-'
    let M =
        (date.getMonth() + 1 < 10 ?
            '0' + (date.getMonth() + 1) :
            date.getMonth() + 1) + '-'
    let D =
        (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '
    let h =
        (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'
    let m =
        (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) +
        ':'
    let s =
        date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
    return Y + M + D + h + m + s
};
const timestampToDay = (timestamp) => {
    if(timestamp == '' || timestamp == undefined || timestamp == null){
      return ''
    }
    if(padEndFun){
      //时间戳为10位需*1000,时间戳为13位的话不需乘1000
      timestamp = padEndFun(timestamp,13,0)
    }
    let date = new Date(timestamp) //时间戳为10位需*1000,时间戳为13位的话不需乘1000
    let Y = date.getFullYear() + '-'
    let M =
        (date.getMonth() + 1 < 10 ?
            '0' + (date.getMonth() + 1) :
            date.getMonth() + 1) + '-'
    let D =
        (date.getDate() < 10 ? '0' + date.getDate() : date.getDate())
    return Y + M + D
};
/**
 * 存储localStorage
 */
const setStore = (name, content) => {
    if (!name) return;
    if (typeof content !== 'string') {
        content = JSON.stringify(content);
    }
    window.localStorage.setItem(name, content);
}

/**
 * 获取localStorage
 */
const getStore = name => {
    if (!name) return;
    return window.localStorage.getItem(name);
}

/**
 * 删除localStorage
 */
const removeStore = name => {
    if (!name) return;
    window.localStorage.removeItem(name);
}

/**
 * 设置cookie
 **/
function setCookie(name, value, day) {
    let date = new Date();
    date.setDate(date.getDate() + day);
    document.cookie = name + '=' + value + ';expires=' + date;
};

/**
 * 获取cookie
 **/
function getCookie(name) {
    let reg = RegExp(name + '=([^;]+)');
    let arr = document.cookie.match(reg);
    if (arr) {
        return arr[1];
    } else {
        return '';
    }
};

/**
 * 删除cookie
 **/
function delCookie(name) {
    setCookie(name, null, -1);
};

/**
 * 导出
 **/
export {
    timestampToTime,
    timestampToDay,
    setStore,
    getStore,
    removeStore,
    setCookie,
    getCookie,
    delCookie
}

以上就是Vue纯前端使用exceljs导出excel文件的完整图文教程的详细内容,更多关于Vue exceljs导出excel的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文