1- 关于excel下载
//excelUtil.js
import XLSX from 'xlsx';
function importExcel(file) {
// 获取上传的文件对象
const { files } = file.target;
// 通过FileReader对象读取文件
const fileReader = new FileReader();
fileReader.onload = event => {
try {
const { result } = event.target;
// 以二进制流方式读取得到整份excel表格对象
const workbook = XLSX.read(result, { type: 'binary' });
let data = []; // 存储获取到的数据
// 遍历每张工作表进行读取(这里默认只读取第一张表)
for (const sheet in workbook.Sheets) {
if (workbook.Sheets.hasOwnProperty(sheet)) {
// 利用 sheet_to_json 方法将 excel 转成 json 数据
data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
// break; // 如果只取第一张表,就取消注释这行
}
}
} catch (e) {
// 这里可以抛出文件类型错误不正确的相关提示
// console.log('文件类型不正确');
return null;
}
};
// 以二进制方式打开文件
fileReader.readAsBinaryString(files[0]);
}
function exportExcel(headers, data, fileName = 'xxx表.xlsx') {
const _headers = headers
.map((item, i) => Object.assign({}, { key: item.key, title: item.title, position: String.fromCharCode(65 + i) + 1 }))
.reduce((prev, next) => Object.assign({}, prev, { [next.position]: { key: next.key, v: next.title } }), {});
const _data = data
.map((item, i) => headers.map((key, j) => Object.assign({}, { content: item[key.key], position: String.fromCharCode(65 + j) + (i + 2) })))
// 对刚才的结果进行降维处理(二维数组变成一维数组)
.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]}`;
// 构建 workbook 对象
const wb = {
SheetNames: ['mySheet'],
Sheets: {
mySheet: Object.assign(
{},
output,
{
'!ref': ref,
'!cols': [{ wpx: 45 }, { wpx: 100 }, { wpx: 200 }, { wpx: 80 }, { wpx: 150 }, { wpx: 100 }, { wpx: 300 }, { wpx: 300 }],
},
),
},
};
// 导出 Excel
XLSX.writeFile(wb, fileName);
}
function saveJSON(data, filename) {
if (!data) {
return;
}
if (!filename) filename = 'json.json'
if (typeof data === 'object') {
data = JSON.stringify(data, undefined, 4)
}
const blob = new Blob([data], { type: 'text/json' });
const e = document.createEvent('MouseEvents');
const a = document.createElement('a');
a.download = filename;
a.href = window.URL.createObjectURL(blob);
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':');
e.initMouseEvent('click', true, false);
a.dispatchEvent(e);
}
//支持大批量数据导出,目前测试15万行 30列通过,导出时间约为6秒
function toLargerCSV(headers, data, fileName = 'xxx表.csv') {
//CSV格式可以自己设定,适用MySQL导入或者excel打开。
//由于Excel单元格对于数字只支持15位,且首位为0会舍弃 建议用 =“数值”
let str = '';
str += `${headers.map(item => `${item?.title}`)}`;
str += '\n';
data.map(item => {
const arr = [];
headers.map(ele => {
arr.push(item[ele?.key])
})
// str += `${Object.values(item || {}).join(',')},\n`
str += `${arr.join(',')},\n`
})
let blob = new Blob([str], { type: 'text/plain;charset=utf-8' });
//解决中文乱码问题
blob = new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type });
const object_url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = object_url;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
//支持大批量数据导出,目前测试15万行 30列通过,导出时间约为6秒
function toLargerCSV(){
//CSV格式可以自己设定,适用MySQL导入或者excel打开。
//由于Excel单元格对于数字只支持15位,且首位为0会舍弃 建议用 =“数值”
var str = '行号,内容,题目,标题\n';
for(let i=0;i<100000;i++){
str += i.toString()+',1234567890123456789\t,张三李四王五赵六,bbbb,\n'
}
var blob = new Blob([str], {type: "text/plain;charset=utf-8"});
//解决中文乱码问题
blob = new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
object_url = window.URL.createObjectURL(blob);
var link = document.createElement("a");
link.href = object_url;
link.download = "导出.csv";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
export default { importExcel, exportExcel, saveJSON, toLargerCSV };
2-xlsx-js-style带样式
npm地址 github地址
//excelUtil.js
// import * as xlsx from "xlsx";
import xlsx from "xlsx-js-style";
function importExcel(file) {
// 获取上传的文件对象
const { files } = file.target;
// 通过FileReader对象读取文件
const fileReader = new FileReader();
fileReader.onload = (event) => {
try {
const { result } = event.target;
// 以二进制流方式读取得到整份excel表格对象
const workbook = XLSX.read(result, { type: "binary" });
let data = []; // 存储获取到的数据
// 遍历每张工作表进行读取(这里默认只读取第一张表)
for (const sheet in workbook.Sheets) {
if (workbook.Sheets.hasOwnProperty(sheet)) {
// 利用 sheet_to_json 方法将 excel 转成 json 数据
data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
// break; // 如果只取第一张表,就取消注释这行
}
}
} catch (e) {
// 这里可以抛出文件类型错误不正确的相关提示
// console.log('文件类型不正确');
return null;
}
};
// 以二进制方式打开文件
fileReader.readAsBinaryString(files[0]);
}
function getSheet(
data,
merges = [],
cols = [
{ wch: 30 },
{ wch: 30 },
{ wch: 30 },
{ wch: 30 },
{ wch: 30 },
{ wch: 30 },
{ wch: 30 },
],
rows = [],
freezepane = {}
) {
const sheet = xlsx.utils.aoa_to_sheet(data); // aoa_to_sheet 将二维数组转成 sheet
//合并规则
// const merges = [
// { s: { r: 1, c: 0 }, e: { r: 4, c: 0 } },
// { s: { r: 5, c: 0 }, e: { r: 8, c: 0 } },
// ];
sheet["!merges"] = merges; // 将merges添加到sheet中,设置合并单元格
// const cols = [
// { wch: 30 },
// { wch: 30 },
// { wch: 30 },
// { wch: 30 },
// { wch: 30 },
// { wch: 30 },
// { wch: 30 },
// ];
sheet["!cols"] = cols; // 将cols添加到sheet中,设置列宽
// const rows = [{ hpx: 30 }, { hpx: 26 }, { hpx: 28 }];
sheet["!rows"] = rows; // 将rows添加到sheet中,设置行高
return sheet;
}
/*
util.default.exportExcel(
[
{
name: "sheet_cy",
data: [
["姓名", "年龄"],
["cy", "18"],
["zq", "16"],
],
},
{
name: "sheet_za",
data: [
["name", "age"],
["cy", "18"],
["zq", "16"],
],
},
],
"cytest.xlsx"
);
* */
function exportExcel(list, fileName = "excel名称.xlsx") {
const workbook = xlsx.utils.book_new(); // 创建虚拟的 workbook
list?.map((item) => {
const sheet = getSheet(
item?.data,
item?.merges || [],
item?.cols || [],
item?.rows || [],
item?.freezepane || {},
);
// 向 workbook 中添加 sheet
xlsx.utils.book_append_sheet(workbook, sheet, item?.name);
});
xlsx.writeFile(workbook, fileName); // 导出 workbook
}
合并规则
let merges = [
//第一列的 0和1合并行
{
s: { r: 0, c: 0 },
e: { r: 1, c: 0 },
},
//第0(首)行第8列和第11列合并
{
s: { r: 0, c: 7 },
e: { r: 0, c: 10 },
},
];
let data1 = [
[
"年份",
"公司名称",
"数据周期",
"主业类型",
"二级目录",
"三级目录",
"四级目录",
"营业收入",
"",
"",
"",
"新签合同额",
"",
"",
"",
"资产总额",
"",
"",
"",
"利润总额",
"",
"",
"",
"投资总额",
"",
"",
"",
"研发费用",
"",
"",
"",
"企业总产值",
"",
"",
"",
]?.map((item) => {
return {
v: item?.toString(),
t: "s",
s: {
// font 字体属性
font: {
bold: true,
sz: 12,
name: "宋体",
},
// alignment 对齐方式
alignment: {
vertical: "center", // 垂直居中
horizontal: "center", // 水平居中
},
border: {
top: {
style: "thin",
color: { rgb: "e1e1e1" },
},
bottom: {
style: "thin",
color: { rgb: "e1e1e1" },
},
left: {
style: "thin",
color: { rgb: "e1e1e1" },
},
right: {
style: "thin",
color: { rgb: "e1e1e1" },
},
},
// fill 颜色填充属性
fill: {
fgColor: { rgb: "F2F3F5" },
},
},
};
}),
[
"年份",
"公司名称",
"数据周期",
"主业类型",
"二级目录",
"三级目录",
"四级目录",
"本期值(万)",
"上年值(万)",
"同比",
"占比",
"本期值(万)",
"上年值(万)",
"同比",
"占比",
"本期值(万)",
"上年值(万)",
"同比",
"占比",
"本期值(万)",
"上年值(万)",
"同比",
"占比",
"本期值(万)",
"上年值(万)",
"同比",
"占比",
"本期值(万)",
"上年值(万)",
"同比",
"占比",
"本期值(万)",
"上年值(万)",
"同比",
"占比",
]?.map((item) => {
return {
v: item?.toString(),
t: "n",
s: {
// font 字体属性
font: {
bold: true,
sz: 12,
name: "宋体",
color: "red",
},
// alignment 对齐方式
alignment: {
vertical: "center", // 垂直居中
horizontal: "center", // 水平居中
},
border: {
top: {
style: "thin",
color: { rgb: "e1e1e1" },
},
bottom: {
style: "thin",
color: { rgb: "e1e1e1" },
},
left: {
style: "thin",
color: { rgb: "e1e1e1" },
},
right: {
style: "thin",
color: { rgb: "e1e1e1" },
},
},
// fill 颜色填充属性
fill: {
fgColor: { rgb: "F2F3F5" },
},
},
};
})
[xx],
....
];
util.default.exportExcel(
[
{
name: "主业统计",
data:data1,
merges,
cols: data1[0]?.map((c, i) => {
if (i == 2) {
return { wch: 40 };
}
return { wch: 20 };
}),
rows: data1[0]?.map((c) => {
return { hpx: 20 };
}),
},
],
name,
);