原創 請回復點贊
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
})
}
小試牛刀

導出效果:

