使用js将表格数据导出成excel文件(xlsx,xlsx-style)
程序员文章站
2024-03-20 21:23:04
...
1.纯文本格式导出,不设置表格样式
直接使用插件xlsx生成表格的数据流,再使用file-saver实现excel文件的导出功能,安装步骤如下:
运行命令:npm install --save xlsx file-saver
import FileSaver from 'file-saver';
import XLSX from 'xlsx';
function downloadExcel(id, fileName) {
/* 从表生成工作簿对象 */
var wb = XLSX.utils.table_to_book(document.querySelector(`#${id}`));
/* 获取二进制字符串作为输出 */
var wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
});
try {
FileSaver.saveAs(
//Blob 对象表示一个不可变、原始数据的类文件对象。
//Blob 表示的不一定是JavaScript原生格式的数据。
//File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
//返回一个新创建的 Blob 对象,其内容由参数中给定的数组串联组成。
new Blob([wbout], {
type: 'application/octet-stream',
}),
//设置导出文件名称
fileName
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, wbout);
}
return wbout;
}
export default downloadExcel;
2.带有样式的excel文件导出
使用xlsx-style生成数据流,执行下载,安装步骤如下:
运行命令:npm install xlsx-style --save
如果引入发生报错:cpexcel.js找不到:
1.在\node_modules\xlsx-style\dist\cpexcel.js 的
2.将 var cpt = require(’./cpt’ + ‘able’);
3.改为 var cpt = cptable;
/* eslint-disable */
import XLSX from 'xlsx-style';
/**
* 定制化导出excel(定制化:附加标题&&样式)
* @param { 表头 } headers
* @param { 数据源 } datasource
* @param { 表格副标题 } options
* @param { 配置文件类型 } type
* @param { 导出的文件名 } fileName
*/
function exportExcel(
headers,
datasource,
options,
type,
fileName = '未命名',
) {
// 处理列宽
const cloWidth = headers.map((item) => ({
wpx: item.width || 60,
}));
// 处理附加表头
const _options = options
.map((item, i) =>
Object.assign({}, {
title: item.title,
position: String.fromCharCode(65) + (i + 1),
})
)
.reduce(
(prev, next) =>
Object.assign({}, prev, {
[next.position]: {
v: next.title,
},
}), {}
);
// 处理表头
const _headers = headers
.map((item, i) =>
Object.assign({}, {
key: item.dataIndex,
title: item.title,
position: String.fromCharCode(65 + i) + (options.length + 1),
})
)
.reduce(
(prev, next) =>
Object.assign({}, prev, {
[next.position]: {
v: next.title,
key: next.key,
},
}), {}
);
// 处理数据源
// 此处如果数据量过大,将可能导致浏览器卡死,所以做了一个分布处理
// max 设置每次循环的最大次数
var _data = {};
var max = 200;
var count = Math.ceil(datasource.length / max);
for (var ic = 0; ic < count; ic++) {
var tmp = datasource
.slice(ic * max, (ic + 1) * max)
.map((item, i) =>
headers.map((col, j) =>
Object.assign({}, {
content: item[col.dataIndex] !== undefined ? item[col.dataIndex] : '',
position: String.fromCharCode(65 + j) +
String(Number(options.length + i + 2 + ic * max)),
})
)
)
.reduce((prev, next) => prev.concat(next))
.reduce(
(prev, next) =>
Object.assign({}, prev, {
[next.position]: {
v: next.content,
},
}), {}
);
Object.assign(_data, tmp);
}
const output = Object.assign({}, _options, _headers, _data);
const outputPos = Object.keys(output); // 设置表格渲染区域,如从A1到C8
// 设置单元格样式,注意,需要循环遍历
for (let col in output) {
output[col].s = {
alignment: {
wrapText: true,
},
};
if (output[col].key) {
output[col].s = {
alignment: {
wrapText: true,
},
fill: {
fgColor: {
rgb: '409eff'
},
},
font: {
color: {
rgb: 'ffffff'
},
},
};
}
}
const wb = {
SheetNames: ['mySheet'], // 保存的表标题
Sheets: {
mySheet: Object.assign({},
output, // 导出的内容
{
'!ref': `${outputPos[0]}:${outputPos[outputPos.length - 1]}`, // 设置填充区域(表格渲染区域)
'!cols': [...cloWidth],
// '!merges': [...merges]
}
),
},
};
// 这种导出方法只适用于js-xlsx,且设置的单元格样式不生效,
// 直接打开下面这两行就行了,后面的可以省略
// XLSX.writeFile(wb,`${fileName}.xlsx`);
// return;
/**
* 以下这种导出方法对于js-xlsx/xlsx-style都适用
* 区别在于import XLSX from 'xlsx-style';可以设置单元格样式
* import XLSX from 'xlsx';不支持设置单元格样式
*
* new Blob转换成二进制类型的对象
*/
const tmpDown = new Blob(
[
s2ab(
XLSX.write(
wb, {
bookType: type == undefined ? 'xlsx' : type.bookType,
bookSST: false,
type: 'binary',
} // 这里的数据是用来定义导出的格式类型
)
),
], {
type: '',
}
);
// 数据都准备完成,可以开始下载excel了
downExcel(
tmpDown,
`${fileName + '.'}${type.bookType == 'biff2' ? 'xls' : type.bookType}`
);
}
/**
* <a>标签下载excel
* @param { Blob对象:二进制的数据 } obj
* @param { 文件名+文件类型后缀 } fileName
*/
function downExcel(obj, fileName) {
const a_node = document.createElement('a');
a_node.download = fileName;
// 兼容ie
if ('msSaveOrOpenBlob' in navigator) {
window.navigator.msSaveOrOpenBlob(obj, fileName);
} else {
// URL.createObjectURL根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里.
// 新的对象URL指向执行的File对象或者是Blob对象.
a_node.href = URL.createObjectURL(obj);
}
a_node.click();
// 每次调用createObjectURL的时候,一个新的URL对象就被创建了.即使你已经为同一个文件创建过一个URL.
// 如果你不再需要这个对象,要释放它,需要使用URL.revokeObjectURL()方法.
// 当页面被关闭,浏览器会自动释放它,但是为了最佳性能和内存使用,当确保不再用得到它的时候,就应该释放它.
setTimeout(() => {
URL.revokeObjectURL(obj);
}, 100);
}
// 字符串转字符流---转化为二进制的数据流
function s2ab(s) {
if (typeof ArrayBuffer !== 'undefined') {
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;
} else {
const buf = new Array(s.length);
for (let i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff;
return buf;
}
}
export default exportExcel;
上一篇: 事务---关于事务的一系列知识
下一篇: 项目数据导出成Excel文件