原创 请回复点赞
1、支持N个列
2、支持复杂表头
安装依赖请看上一篇文章 点击这里
废话不多说 ,直接上码
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
})
}
小试牛刀

导出效果:

