文本通过转换 antd-table 的数据格式,通过之前的文章 xlsx-style 在 express 中的应用 ,使用 xlsx-style 组件库的 express 的接口,导出带样式的 excel 文件。下面是一个与antd table的数据格式转换的一个实例,大家可以参考来进行改造,将 antd table 与 xlsx-style 组件库进行打通,前端进行 excel 文件导入导出,而不需要依赖 java 后台。
import { message } from 'antd'
import { getCookie } from './cookie'
/**
* [s] cell style property 共4个顶级属性
* 1. {fill}
* -------------------------------------
* patternType: solid|node 有无
* fgColor: COLOR_SPEC 文本色
* bgColor: COLOR_SPEC 背景色
* -------------------------------------
* 2. {font}
* -------------------------------------
* name: 字体 // default "Calibri"
* sz: 字体大小 // default "11"
* color: 颜色
* bold: 加粗 // true || false
* underline: 下划线 // true || false
* italic: 斜体 // true || false
* strike: 删除线 // true || false
* outline: 轮廓线 // true || false
* shadow: 阴影 // true || false
* vertAlign: **
* ------------------------------------
* 3. {alignment}
* ------------------------------------
* vertical: 垂直 // "bottom"||"center"||"top"
* horizontal: 水平 // "bottom"||"center"||"top"
* wrapText: 本文超出自动换行 // true || false
* readingOrder: 阅读方式 // 2 从右到左
* textRotation: 旋转 // Number from 0 to 180 or 255 (default is 0)
* ------------------------------------
* 4. {border}
* ------------------------------------
* top/bottom/left/right: { style: BORDER_STYLE, color: COLOR_SPEC }
* diagonal: 对角线 { style: BORDER_STYLE, color: COLOR_SPEC }
* diagonalUp/diagonalDown: 两种对角线的方式 true||false
* ------------------------------------
* 【注】BORDER_STYLE:边框样式是一个字符串值,可以采用以下值之一:
* thin | medium | thick | dotted | hair | dashed | mediumDashed | dashDot | mediumDashDot
* dashDotDot | mediumDashDotDot | slantDashDot
*/
const headerStyleDefault = {
fill: { fgColor: { rgb: '38364B' } },
font: { sz: '14', name: '华文宋体', bold: true, color: { rgb: 'F6F6F6' } },
alignment: { horizontal: 'center', vertical: 'center', wrapText: true, readingOrder: 2 },
border: {
top: { style: 'thin', color: { rgb: '000000' } },
bottom: { style: 'thin', color: { rgb: '000000' } },
left: { style: 'thin', color: { rgb: '000000' } },
right: { style: 'thin', color: { rgb: '000000' } }
}
}
const bodyStyleDefault = {
font: { sz: '14', name: '华文宋体' },
fill: { bgColor: { indexed: 64 }, fgColor: { rgb: 'F2F2F2' } },
border: {
top: { style: 'thin', color: { rgb: 'BCBCBC' } },
bottom: { style: 'thin', color: { rgb: 'BCBCBC' } },
left: { style: 'thin', color: { rgb: 'BCBCBC' } },
right: { style: 'thin', color: { rgb: 'BCBCBC' } }
},
alignment: { horizontal: 'center', vertical: 'center' }
}
const sideStyleDefault = {
fill: { bgColor: { indexed: 64 }, fgColor: { rgb: 'B1D9F5' } },
font: { sz: '14', name: '华文宋体' },
border: {
top: { style: 'thin', color: { rgb: '000000' } },
bottom: { style: 'thin', color: { rgb: '000000' } },
left: { style: 'thin', color: { rgb: '000000' } },
right: { style: 'thin', color: { rgb: '000000' } }
}
}
/**
* workSheet 的 Sheet 参数,用来进行设置 【!merges合并单元格】【!cols设置列宽】
* e.g.
*/
// cols 设置单元格每一列的宽度,该数组第一位是第一列,依此类推,不设置为默认宽度
const sheetColsDefault = [{ wch: 20 }, { wch: 20 }, { wch: 20 }]
// merges s:起始单元格,e:结束单元格;c(列号)和r(行号),是以0为开头的索引。以合并的第一个单元格value进行填充内容
const sheetMergesDefault = [{
s: { c: 0, r: 0 },
// 第1列 第1行//
e: { c: 3, r: 1 }
//第4列 第2行
}]
/**
* operate progress
* 1.需要将json数据从this.response取出
* 2.将json数据转成buffer流
* 3.将buffer流数据转成blob类型,用于在a标签中导出
* 4.在a标签中导出数据
* 【注】fileHeader 数据类型:
* [
* { title: '',
* key: '',
* children: [
* {
* title: '',
* key: '',
* }
* ]
* },
* {
* title: '',
* key: '',
* },
* ]
*/
/** -------- API start ----------
* 参数 说明 类型 默认值 是否必填
* fileData excel数据 object {...} true
* —>fileName excel文件名 stying 'report' false
* ->fileHeader table表头 [{...}] [{...}] true
* ->fileHeaderKey tableBody键值 [] [] true
* ->fileBody tableBody [{...}] [{...}] true
* sheetStyle excel样式 object {...} false
* ->headerStyle 表头样式 object headerStyleDefault false
* ->bodyStyle 内容样式 object bodyStyleDefault false
* ->sideStyle 侧边栏样式 object sideStyleDefault false
* sheetCols 设置excel列宽 array [{}] false
* sheetMerges 单元格合并 array [{}] false
* isNeedSideStyle 侧边栏样式 bool true false
* isNeedSideWidth 侧边栏默认20宽度 bool true false
* isNeedBodyStyleCross body交错样式 bool true false
* --------- API end -----------
*/
function xlsxStyleExport(sheetData = {}) {
const {
fileData,
sheetStyle = {},
sheetCols = [],
sheetMerges = [],
isNeedSideWidth = true,
isNeedSideStyle = true,
isNeedBodyStyleCross = true
} = sheetData
const styleDefaultParams = {
headerStyle: headerStyleDefault,
bodyStyle: bodyStyleDefault,
bodyStyleBlank: { ...bodyStyleDefault, fill: { fgColor: { rgb: 'FFFFFF' } } },
sideStyle: isNeedSideStyle ? sideStyleDefault : bodyStyleDefault, ...sheetStyle
}
const fileDataParams = {
fileHeader: fileData.fileHeader || [],
fileBody: fileData.fileBody || [],
fileName: fileData.fileName || ''
}
// eslint-disable-next-line no-nested-ternary
const sheetColsParams = sheetCols.length ? sheetCols : (isNeedSideWidth ? sheetColsDefault : [])
const sheetMergesParams = sheetMerges.length ? sheetMerges : []
const params = {
style: styleDefaultParams,
fileData: fileDataParams,
sheetCols: sheetColsParams,
sheetMerges: sheetMergesParams,
isNeedBodyStyleCross,
isNeedSideStyle
}
fetch(new Request('/elxsStyle/export', {
credentials: 'same-origin',
method: 'POST',
headers: new Headers({
ddjjuuid: getCookie('ddjjuuid'),
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json',
pragma: 'no-cache',
'cache-control': 'no-cache'
}),
body: JSON.stringify(params)
})).then(response => response.json()).then((res) => {
if (res.code === '0') {
const buffer = Buffer.from(res.data.data)
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' })
const url = URL.createObjectURL(blob)
const linkElement = document.createElement('a')
// 创建点击下载的元素
linkElement.setAttribute('href', url)
linkElement.setAttribute('downLoad', `${fileData.fileName || 'report'}.xlsx`)
const evt = document.createEvent('MouseEvents')
// 兼容火狐浏览器不支持a标签点击事件
evt.initEvent('click', true, true)
linkElement.dispatchEvent(evt)
linkElement.remove()
} else {
message.error('导出文件失败,请重试')
}
})
}
export default xlsxStyleExport