上一次大概讲了下导出execel的比较简单的做法,这回补上一个更简单的方法,就用execel导出的。比较方便,不多叙述
大体思路很简单,就是
1.先将数据放在一个数组中,整理成为一个数组
2.保存到table格式的文本中
3.更新table的数据,走execel的路线进行封装
4.将table转化为流的方式,写进去(二进制的操作,这个是必走之路)
大概难点在三个
1.数组长什么样子?
2.table怎么封装成execel的格式
3.怎么转化为流
代码其实很简单,没有啥,就不废话了,静心下来,看逻辑,是可以看懂的,写的也很直白,没用复杂的写法,可能需要有一定的ts基础,但是我还是觉得写得够多了,注释
/**
* @typedef 数组返回拼接字符串格式
* @param tableRows Array 表格字符串列表
* @returns fullTemplateStr string 拼接完成的字符串
*/
private arrayToTableStr(tableRows: Array<string>) {
// 最后完整的字符串内容
let fullTemplateStr = ''
//拼接整个头部
fullTemplateStr += template.head
// 增加sheet的头部
fullTemplateStr += template.sheet.head
// 加上内容
fullTemplateStr += 'sheet1'
// 增加sheet的尾部
fullTemplateStr += template.sheet.tail
// 增加上中间的部分
fullTemplateStr += template.mid
fullTemplateStr += template.table.head
// 加上正式内容
tableRows.forEach((row) => {
fullTemplateStr += row
})
fullTemplateStr += template.table.tail
//拼接整个尾部
fullTemplateStr += template.foot
return fullTemplateStr
}
/**
* @typedef a链接导出
* @param fileName 文件名称
* @param linkUrl 链接
* @param fileExtension 文件后缀
*/
private createLink(linkUrl: string, fileName?: String, fileExtension?: FileType) {
fileExtension = fileExtension || FileType.xml//默认类型为xml
let aTag = document.createElement('a')
aTag.download = `${fileName || this.fileName}.${fileExtension}`
document.body.appendChild(aTag)
aTag.href = linkUrl
aTag.click()
document.body.removeChild(aTag)
}
/**
* @description 将表格的每一项创建并添加到数据中
* @param titleArray Array 标题列表
* @param jsonData 内容体
* @param styleList 样式列表
*/
private createRowArray(titleArray: Array<string>, jsonData: Array<string>, styleList?: any) {
const tableRows = []//放数据的地方
// let computedStyle = {}//计算过后的样式对象
let row = ''
// 需要把头的也遍历一边,后面需要拼接
// row += `<tr style=' ${computedStyle} '>`
row += '<tr>'
// 竖排
titleArray.forEach(td => {
row += `<td>${td}</td>`
})
row += '</tr>'
// 每一列都加上去
tableRows.push(row)
// 便利获取到样式以及元素的k-v,拼接起来
// 横排
jsonData.forEach(tr => {
row = '<tr>'
// 竖排
Object.keys(tr).forEach(td => {
styleList[td] ? row += `<td${styleList[td]}>${tr[td]}</td>` : row += `<td>${tr[td]}</td>`
})
row += '</tr>'
// 每一列都加上去
tableRows.push(row)
})
return tableRows
}
/**
*@typedef 把样式拼接成字符串的形式
*@param styleList Array 样式对象
*/
private formatStyle2String(styleList: any) {
if (!styleList || styleList.length === 0) { return [] };
const _styleList = []
Object.keys(styleList).forEach((styleKey) => {
let str = ' style=\''//注意,这儿是空了一个格子的
Object.keys(styleList[styleKey]).forEach(_o => {
str += `${_o}:${styleList[styleKey][_o]};`
})
str.slice(str.length, 1)//除去最后的空格,毕竟还是要严谨点的
str += '\' '//注意,最后也是空了一个格子的
_styleList[styleKey] = str
})
return _styleList
}
/**
* @typedef 以table的形式导出execel文件
* @param titleArray 标题 Array ['标题1', '标题2', '标题3', '标题4']
* @param jsonData 内容体 Array [{k1:v1,k2:v2}]
*/
public createByTable(titleArray: Array<string>, jsonData: Array<any>, styleList?: Array<Istyle>) {
const styleArray = this.formatStyle2String(styleList)
const data = this.createRowArray(titleArray, jsonData, styleArray)
// 封装成为一个sheet
let blob = new Blob([this.arrayToTableStr(data)], { type: 'application/vnd.ms-excel' })
//解决中文乱码问题
blob = new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type })
this.createLink(window.URL.createObjectURL(blob), this.fileName, FileType.xls)
// 遍历数组,获取k-v,
}
// 枚举类
export enum FileType {
csv = 'csv',
xml = 'xml',
xls = 'xls'
}
// 接口
export interface Ictx {
worksheet: string,
table: string,
sheetName: string
}
export interface IstyleList {
[name: string]: Istyle
}
// 单个样式的实例
export interface Istyle {
'text-align': string,
'background-color': string,
// ['background-color':string]:string
width?: string,//宽度 100(px)
height?: string,//高度 100(px)
color?: string//颜色 #00ff00
border: string//border 1px solid #ccc
}
//静态变量
// table转化需要的变量
const utf8Heading = '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">'
// table的需要模板
export const template = {
head: '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">' + utf8Heading + '<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets>',
sheet: {
head: '<x:ExcelWorksheet><x:Name>',
tail: '</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>'
},
mid: '</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body>',
table: {
head: '<table>',
tail: '</table>'
},
foot: '</body></html>'
}
使用简单是简单,但是兼容性没做测试,如果实际使用,建议用比较多星的库,或则帮我测测兼容,留言我来改,因为可能是execel导出系列的最后一篇(objectxactive的估计不会写),所以罗索下,最好后台导出,因为前端导出会卡,测试了导出10w条简单的数据,大概需要10s
npm: [aexecel](https://www.npmjs.com/package/aexecel)
github:[aexecel](https://github.com/mkhbz/aexecel)