zoukankan      html  css  js  c++  java
  • vue中前端导出excel表,使用Export2Excel导出多级表头的表格

    原创 请回复点赞

    1、支持N个列

    2、支持复杂表头

    安装依赖请看上一篇文章 点击这里

    废话不多说 ,直接上码

     excelHelper

    import { export_json_to_excel } from './vendor/Export2Excel'
    // import excel from '@/vendor/Export2Excel'
    // 行转列
    function formatJson(filterVal, jsonData) {
      return jsonData.map(v =>
        filterVal.map(j => {
          return v[j]
        })
      )
    }
    
    let CURRENT_CELL_INDEX = 0
    // https://segmentfault.com/q/1010000023268006?utm_source=tag-newest
    //转换数字到EXCEL单元格编号
    function numberToCellCode(number) {
      let s = ''
      while (number > 0) {
        let m = number % 26
        if (m === 0) m = 26
        s = String.fromCharCode(m + 64) + s
        number = (number - m) / 26
      }
      return s
    }
    // 获取跨列
    function getColspan(column) {
      var colspan = 0
      var children = column.children || []
      for (var i = 0; i < children.length; i++) {
        var item = children[i]
        if (item.children && item.children.length > 0) {
          colspan += getColspan(item)
        } else {
          colspan += 1
        }
      }
      if (colspan == 0) {
        colspan = 1
      }
      return colspan
    }
    // 获取跨列
    function getRowspan(column, maxLevel) {
      let rowspan = 1
      if (!column.children || column.children.length == 0) {
        rowspan = maxLevel - column.level + 1
      }
      return rowspan
    }
    // 获取最大层级
    function setCellCode(columns, parentNode) {
      const levels = []
      columns.forEach((li, index) => {
        if (!CURRENT_CELL_INDEX) {
          CURRENT_CELL_INDEX = 1
        } else {
          CURRENT_CELL_INDEX++
        }
        if (parentNode && index == 0) {
          CURRENT_CELL_INDEX = parentNode.CellIndex
        }
        li.CellIndex = CURRENT_CELL_INDEX
        li.CellCode = numberToCellCode(CURRENT_CELL_INDEX)
        const children = li.children
        if (children && children.length > 0) {
          setCellCode(children, li)
        }
      })
      return levels
    }
    // 获取最大层级
    function getLevels(columns, parentNode) {
      const levels = []
      columns.forEach((li, index) => {
        li.level = parentNode ? parentNode.level + 1 : 0
        levels.push(li.level)
        const children = li.children
        if (children && children.length > 0) {
          const result = getLevels(children, li)
          levels.push(...result)
        }
      })
      return levels
    }
    // 设置合并
    function setMerges(columns = [], maxLevel, multiHeader = [], merges = []) {
      columns.forEach((li, index) => {
        const level = li.level + 1
        const cellIndex = li.CellIndex - 1
        const CellCode = li.CellCode
        const cellTitle = li.label
        const colSpan = getColspan(li)
        const rowSpan = getRowspan(li, maxLevel)
    
        li.colSpan = colSpan
        li.rowSpan = rowSpan
        if (!multiHeader[level - 1]) {
          multiHeader[level - 1] = []
        }
        debugger
        if (rowSpan > 1) {
          merges.push(`${CellCode}${level}:${CellCode}${level + rowSpan - 1}`)
          multiHeader[level - 1][cellIndex] = cellTitle
          for (let i = 1; i < rowSpan; i++) {
            if (!multiHeader[level - 1 + i]) {
              multiHeader[level - 1 + i] = []
            }
            multiHeader[level - 1 + i][cellIndex] = ''
          }
        } else {
          multiHeader[level - 1][cellIndex] = cellTitle
        }
        if (colSpan > 1) {
          let endCellIndex = cellIndex
          let emptyCell = []
          for (let i = 1; i < colSpan; i++) {
            endCellIndex++
            emptyCell.push('')
          }
          const endCellCode = numberToCellCode(endCellIndex)
          multiHeader[level - 1].splice(cellIndex + 1, 0, ...emptyCell)
          merges.push(`${CellCode}${level}:${endCellCode}${level}`)
        }
        const children = li.children
        if (children && children.length > 0) {
          setMerges(children, maxLevel, multiHeader, merges)
        }
      })
    }
    /**
     * 文件导出
     * @param tableData {Array} 数据源
     * @param columns {Array} 列
     * @param config {Object} 配置项
     */
    export function exportToExcel(tableData, columns, config) {
      const option = { filename: '数据导出', autoWidth: true, bookType: 'xlsx' }
      if (config) {
        Object.assign(option, config)
      }
      let multiHeader = []
      const header = []
      const merges = []
      CURRENT_CELL_INDEX = 0
      setCellCode(columns, null, null)
      // console.log('setCellCode', columns)
      // 最大层级集合
      const allLevels = getLevels(columns, null)
      // 获取最大层级
      const maxLevel = Math.max(...allLevels)
      // console.log(maxLevel)
      setMerges(columns, maxLevel, multiHeader, merges)
      // console.log('multiHeader', JSON.stringify(multiHeader, null, 4))
      // console.log('setMerges', merges)
      header.push(...multiHeader[maxLevel])
      if (maxLevel > 0) {
        multiHeader.splice(maxLevel, 1)
      } else {
        multiHeader = []
      }
      // 行转列
      const filterVal = []
      columns.forEach(row => {
        filterVal.push(row.prop)
      })
      const data = formatJson(filterVal, tableData)
      export_json_to_excel({
        multiHeader,
        header,
        merges,
        data,
        filename: option.filename,
        autoWidth: option.autoWidth,
        bookType: option.bookType
      })
    }
    View Code

     小试牛刀

    导出效果:

    如果这篇文章对您有帮助,您可以打赏我

    技术交流QQ群:15129679

  • 相关阅读:
    AVAYA语音通知管理
    如何打出强烈低杆
    iSCSI存储技术全攻略
    域控制器的管理注意事项
    Ogre的ExampleApplication阅读
    CEImagesetEditor编译过程
    Ogre基础教程遇到的问题
    SQLServer中进行sql除法运算结果为小数时显示0的解决方案
    【全面解禁!真正的Expression Blend实战开发技巧】第五章 从最常用ButtonStyle开始 ImageButton
    silverlight,WPF动画终极攻略之白云飘,坐车去旅游篇(Blend 4开发)
  • 原文地址:https://www.cnblogs.com/yeminglong/p/14700100.html
Copyright © 2011-2022 走看看