npm install xlsx file-saver
import { saveAs } from 'file-saver'
import XLSX from 'xlsx'
function datenum(v, date1904) {
if (date1904) v += 1462
const epoch = Date.parse(v)
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
}
function sheet_from_array_of_arrays(data) {
const ws = {}
const range = {
s: {
c: 10000000,
r: 10000000
},
e: {
c: 0,
r: 0
}
}
for (let R = 0; R !== data.length; ++R) {
for (let C = 0; C !== data[R].length; ++C) {
if (range.s.r > R) range.s.r = R
if (range.s.c > C) range.s.c = C
if (range.e.r < R) range.e.r = R
if (range.e.c < C) range.e.c = C
const cell = {
v: data[R][C]
}
if (cell.v === null) continue
const cell_ref = XLSX.utils.encode_cell({
c: C,
r: R
})
if (typeof cell.v === 'number') cell.t = 'n'
else if (typeof cell.v === 'boolean') cell.t = 'b'
else if (cell.v instanceof Date) {
cell.t = 'n'
cell.z = XLSX.SSF._table[14]
cell.v = datenum(cell.v)
} else cell.t = 's'
ws[cell_ref] = cell
}
}
if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)
return ws
}
function Workbook() {
if (!(this instanceof Workbook)) return new Workbook()
this.SheetNames = []
this.Sheets = {}
}
function s2ab(s) {
const buf = new ArrayBuffer(s.length)
const view = new Uint8Array(buf)
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
return buf
}
export function export_json_to_excel({
autoWidth = true,
bookType = 'xlsx',
data,
filename,
header,
merges = [],
multiHeader = []
} = {}) {
filename = filename || 'excel-list'
data = [...data]
data.unshift(header)
for (let i = multiHeader.length - 1; i > -1; i--) {
data.unshift(multiHeader[i])
}
const ws_name = 'SheetJS'
const wb = new Workbook()
const ws = sheet_from_array_of_arrays(data)
if (merges.length > 0) {
if (!ws['!merges']) ws['!merges'] = []
merges.forEach((item) => {
ws['!merges'].push(XLSX.utils.decode_range(item))
})
}
if (autoWidth) {
/* 设置worksheet每列的最大宽度*/
const colWidth = data.map((row) =>
row.map((val) => {
/* 先判断是否为null/undefined*/
if (val === null) {
return {
wch: 12
}
} else if (val.toString().charCodeAt(0) > 255) {
/* 再判断是否为中文*/
return {
wch: val.toString().length * 3
}
} else {
return {
wch: val.toString().length + 10
}
}
})
)
/* 以第一行为初始值*/
const result = colWidth[0]
for (let i = 1; i < colWidth.length; i++) {
for (let j = 0; j < colWidth[i].length; j++) {
if (result[j].wch < colWidth[i][j].wch) {
result[j].wch = colWidth[i][j].wch
}
}
}
ws['!cols'] = result
}
/* add worksheet to workbook */
wb.SheetNames.push(ws_name)
wb.Sheets[ws_name] = ws
const wbout = XLSX.write(wb, {
bookType,
bookSST: false,
type: 'binary'
})
saveAs(
new Blob([s2ab(wbout)], {
type: 'application/octet-stream'
}),
`${filename}.${bookType}`
)
}
/**
* 格式化JSON数据
* @param filterVal
* @param jsonData
* @returns {*}
*/
function formatJson(filterVal, jsonData) {
return jsonData.map((v) =>
filterVal.map((j) => {
return v[j] ? v[j] : ''
})
)
}
导出单个 sheet
/**
* JSON数据导出excel
* @param { name, header, headerKeys, data } 参数集合
*/
export function exportJsonToExcel({ data, filename, header, headerKeys }) {
filename = filename || `tr-export-${new Date().getTime()}`
const resultData = formatJson(headerKeys, data)
export_json_to_excel({
header,
data: resultData,
filename
})
}
调用
const data = [{name: 'Bob', age: 18}, {name: 'Joe', age: 18}]
const header = ['姓名', '年龄']
const headerKeys = ['name', 'age']
exportJsonToExcel({ data, header, headerKeys })
导出多个 sheet
export function json2excelMuti(tableJson, filenames) {
const tHeader = []
const dataArr = []
const sheetnames = []
const multiHeader = []
const merges = []
for (const i in tableJson) {
tHeader.push(tableJson[i].tHeader)
dataArr.push(formatJson(tableJson[i].filterVal, tableJson[i].tableDatas))
sheetnames.push(tableJson[i].sheetName)
multiHeader.push(tableJson[i].multiHeader || [])
merges.push(tableJson[i].merges || [])
}
export_json_to_excel({
multiHeader,
merges,
header: tHeader,
data: dataArr,
sheetname: sheetnames,
filename: filenames
})
}
调用
const data = [
{ data: [{name: 'Bob', age: 18}, {name: 'Joe', age: 18}], tHeader: ['姓名', '年龄'], filterVal: ['name', 'age'], sheetName: 'sheet1' },
{ data: [{name: 'Bob', age: 18}, {name: 'Joe', age: 18}], tHeader: ['姓名', '年龄'], filterVal: ['name', 'age'], sheetName: 'sheet2' }
]
json2excelMuti(data, '导出文件名')