近期做了一个react ant design 的table转换成excel 的功能 总结下
首先我们会自己定义下 antdesign 的table的columns其中有可能有多语言或者是render方法的转换显示(比如说加特殊符号或者属性的code转换成对应的显示名称)都可以应用上
比如
const columns = [{ title: 'Qty', dataIndex: 'quantity', key: 'quantity' }, { title: intl.get("totaldiscount").d('Total Discount Price'), dataIndex: 'price', key: 'price', render: text => { var msg = text switch (text) { case "": '' break; default: msg => "¥" + msg break; } return msg } }]
const data=[{qty:1,price;10},{qty:2,price;20}]
exportExcel([headers:columns,data:data,sheetName:"销售数据sheet" ],"统计报表")
添加一个文件写exportExcel的function
支持同时生成多个sheet
1 import XLSX from 'xlsx'; 2 //exportExcel sheets=[{headers:[],data:[],sheetName:""}] fileName ="" 3 function exportExcel(sheets, fileName = 'dowloadFile') { 4 const sheetsArr = sheets.map(sheet => { 5 const _headers = sheet.headers 6 .map((item, i) => Object.assign({}, { key: item.key, title: item.title, position: getPostition(i) + 1 })) 7 .reduce((prev, next) => Object.assign({}, prev, { [next.position]: { key: next.key, v: next.title } }), {}); 8 const dataArr = sheet.data 9 .map((item, i) => sheet.headers.map((head, j) => { 10 let content = "" 11 if (head.render) { 12 content = head.render(item[head.dataIndex], item) 13 } else { 14 content = item[head.dataIndex] 15 } 16 return { content, position: getPostition(j) + (i + 2) } 17 } 18 )) 19 // 对刚才的结果进行降维处理(二维数组变成一维数组) 20 const _data = dataArr.reduce((prev, next) => prev.concat(next)) 21 // 转换成 worksheet 需要的结构 22 .reduce((prev, next) => Object.assign({}, prev, { [next.position]: { v: next.content } }), {}); 23 24 // 合并 headers 和 data 25 const output = Object.assign({}, _headers, _data); 26 // 获取所有单元格的位置 27 const outputPos = Object.keys(output); 28 // 计算出范围 ,["A1",..., "H2"] 29 const ref = `${outputPos[0]}:${outputPos[outputPos.length - 1]}`; 30 return Object.assign( 31 { sheetName: sheet.sheetName }, 32 output, 33 { 34 '!ref': ref, 35 '!cols': getColWidth(sheet.headers, dataArr), 36 }, 37 ) 38 }) 39 const sheetNames = sheetsArr.map(sheet => sheet.sheetName) 40 const wbSheets = sheetsArr.reduce((prev, next) => 41 Object.assign({}, prev, { [next.sheetName]: next }), {}) 42 // 构建 workbook 对象 43 const wb = { 44 SheetNames: sheetNames, 45 Sheets: wbSheets, 46 }; 47 // 导出 Excel 48 XLSX.writeFile(wb, fileName + ".xlsx"); 49 } 50 51 function getPostition(index) { 52 let result = String.fromCharCode(65 + parseInt(index % 26)) 53 let value = index / 26 54 while (value >= 1) { 55 result = String.fromCharCode(65 + parseInt(value % 26 - 1)) + result 56 value = parseInt(value / 26) 57 } 58 return result 59 } 60 function getColWidth(headers, dataArr) { 61 const allWch = [headers,].concat(dataArr).map(item => item.map(val => { 62 let value = val.title || val.content || "" 63 let length = 10 64 /*先判断是否为null/undefined*/ 65 if (value) { 66 /*再判断是否为中文*/ 67 if (value.toString().charCodeAt(0) > 255) { 68 length = value.toString().length * 2 69 } else { 70 length = value.toString().length 71 } 72 } 73 return { 74 'wch': length < 40 ? length : 40 75 }; 76 })) 77 /*以第一行为初始值*/ 78 let colWidth = allWch[0]; 79 for (let i = 1; i < allWch.length; i++) { 80 for (let j = 0; j < allWch[i].length; j++) { 81 if (colWidth[j]['wch'] < allWch[i][j]['wch']) { 82 colWidth[j]['wch'] = allWch[i][j]['wch']; 83 } 84 } 85 } 86 return colWidth 87 } 88 export default exportExcel;
import
XLSX
from
'xlsx';
//exportExcel sheets=[{headers:[],data:[],sheetName:""}] fileName =""
function
exportExcel(
sheets,
fileName =
'dowloadFile') {
const
sheetsArr =
sheets.
map(
sheet
=> {
const
_headers =
sheet.
headers
.
map((
item,
i)
=>
Object.
assign({}, {
key:
item.
key,
title:
item.
title,
position:
getPostition(
i) +
1 }))
.
reduce((
prev,
next)
=>
Object.
assign({},
prev, {
[next.position]: {
key:
next.
key,
v:
next.
title } }), {});
const
dataArr =
sheet.
data
.
map((
item,
i)
=>
sheet.
headers.
map((
head,
j)
=> {
let
content =
""
if (
head.
render) {
content =
head.
render(
item[
head.
dataIndex],
item)
}
else {
content =
item[
head.
dataIndex]
}
return {
content,
position:
getPostition(
j) + (
i +
2) }
}
))
// 对刚才的结果进行降维处理(二维数组变成一维数组)
const
_data =
dataArr.
reduce((
prev,
next)
=>
prev.
concat(
next))
// 转换成 worksheet 需要的结构
.
reduce((
prev,
next)
=>
Object.
assign({},
prev, {
[next.position]: {
v:
next.
content } }), {});
// 合并 headers 和 data
const
output =
Object.
assign({},
_headers,
_data);
// 获取所有单元格的位置
const
outputPos =
Object.
keys(
output);
// 计算出范围 ,["A1",..., "H2"]
const
ref =
`
${
outputPos[
0]
}
:
${
outputPos[
outputPos.
length -
1]
}
`;
return
Object.
assign(
{
sheetName:
sheet.
sheetName },
output,
{
'!ref'
:
ref,
'!cols'
:
getColWidth(
sheet.
headers,
dataArr),
},
)
})
const
sheetNames =
sheetsArr.
map(
sheet
=>
sheet.
sheetName)
const
wbSheets =
sheetsArr.
reduce((
prev,
next)
=>
Object.
assign({},
prev, {
[next.sheetName]:
next }), {})
// 构建 workbook 对象
const
wb = {
SheetNames:
sheetNames,
Sheets:
wbSheets,
};
// 导出 Excel
XLSX.
writeFile(
wb,
fileName +
".xlsx");
}
function
getPostition(
index) {
let
result =
String.
fromCharCode(
65 +
parseInt(
index %
26))
let
value =
index /
26
while (
value >=
1) {
result =
String.
fromCharCode(
65 +
parseInt(
value %
26 -
1)) +
result
value =
parseInt(
value /
26)
}
return
result
}
function
getColWidth(
headers,
dataArr) {
const
allWch = [
headers,].
concat(
dataArr).
map(
item
=>
item.
map(
val
=> {
let
value =
val.
title ||
val.
content ||
""
let
length =
10
/*先判断是否为null/undefined*/
if (
value) {
/*再判断是否为中文*/
if (
value.
toString().
charCodeAt(
0) >
255) {
length =
value.
toString().
length *
2
}
else {
length =
value.
toString().
length
}
}
return {
'wch'
:
length <
40 ?
length :
40
};
}))
/*以第一行为初始值*/
let
colWidth =
allWch[
0];
for (
let
i =
1;
i <
allWch.
length;
i++) {
for (
let
j =
0;
j <
allWch[
i].
length;
j++) {
if (
colWidth[
j][
'wch'] <
allWch[
i][
j][
'wch']) {
colWidth[
j][
'wch'] =
allWch[
i][
j][
'wch'];
}
}
}
return
colWidth
}
export
default
exportExcel;