当我在使用xlsx包导出csv文件时候,数据过大导致页面卡死,因此才使用blob的方式来导出csv文件,如果没有出现这个问题,建议还是使用xlsx包
npm的地址,对于前后端开发的同学来说,文档难度不大,大概看下就可以快速上手,且当前开发的最高版本为0.18.5,项目使用也很稳定
https://www.npmjs.com/package/xlsx
当数据量大于某个值的时候(需要看你当时的内存,有时候可能一两个g都没问题,有时候可能100m都炸),会导致页面的卡死,基本是因为使用xlsx的时候,生成每一个sheet的时候,传入的数据形式类似下面
let array1 = new Array(10).fill({
name: 'mk',
age: "18"
});
数据大概如下,就是一个长度为10的数组对象。
当数据量不会太大的时候,内存并不会溢出,也就是说页面并不会卡死,数据量较少时候放在前端,是一个很明智的选择。但当你把导出excel的功能放在前端的时候,你就必须考虑一个内存会爆的情况。这时候可以尝试使用blob的形式导出csv文件。我想你也不会想我花两三个小时的时间解释Blob的作用,直接上代码吧。
const downloadFunction = (dataArray) => {
document.getElementById('download').onclick = function () {
var csvRows = dataArray;
var csvString = csvRows.join("\r\n");
var csvData = new Blob([csvString], { type: 'text/csv' });
var a = document.createElement('a');
a.href = URL.createObjectURL(csvData);
a.target = '_blank';
a.download = 'export.csv';
document.body.appendChild(a);
a.click();
}
}
上述的代码没有啥理解的难度,主要是生成一个下载名为export.csv的文件,对传进去的数据的处理逻辑也只是将数组转化为string,并且添加空格作为切割,以及将其转化为blob,并导出去。
先来一波最简单的压力测试,让大家大概地了解下用法。
const downloadFunction = (dataArray) => {
document.getElementById('download').onclick = function () {
var csvRows = dataArray;
var csvString = csvRows.join("\r\n");
var csvData = new Blob([csvString], { type: 'text/csv' });
var a = document.createElement('a');
a.href = URL.createObjectURL(csvData);
a.target = '_blank';
a.download = 'export.csv';
document.body.appendChild(a);
a.click();
}
}
let column = ["name", "age"];
const data = ["mk", "18"];
let array = new Array(100000).fill(data);
downloadFunction([column, ...array]);
生成了一个最简单的excel,生成了一个csv文件,大概内容如下
对于csv文件,百度的解释是这样的
逗号分隔值(Comma-Separated
Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。
因此,对于数据中的逗号,需要做一些处理,比如下面这种情况。
这儿对数据的格式做了处理,比如,将其添加了一个逗号,这样子,会出现下面的这种情况,数据“mk, a coder” 被csv文件切割成了"mk", "a coder"这两个不同的格子里面。
所以,对逗号的处理,需要添加下面的这种操作,这儿修改下,只生成两个数组
let array = new Array(2)
.fill(data.map(string => string === null ? '' : `\"${string}\"`));
console.log(array);
ok,逗号的问题,暂时解决了。接下来要处理的,是数字的问题,大家应该都有发现,我这儿用的数字是18,但是如果是用户的编号,类似00001这样子的话,生成的csv文件,会出问题。如下:
所以,需要再加一个数字的处理,具体逻辑就是加一个"\t",具体可以百度下是什么意思,我就不喜欢做保姆了。
let array = new Array(2)
.fill(
data
// 对数字格式的字符串做处理
.map(string => { if (!!parseInt(string)) { return `\t${string}` } })
// 对逗号做处理
.map(string => string === null ? '' : `\"${string}\"`)
);
接下来还有一个问题,当我们将数据修改为如下的格式的时候。
let column = ["name", "age", "description", "remark"];
const data = ["mk, a coder",
"000018",
'{"desc1":"desc1","desc2":"desc2"}',
'the remarks is: {"remark1":"remark2","reamrk3":"remark4"}'
];
可以看到新的数据,他们多增加了一个双引号,这就导致了我们生成的csv文件中,在有逗号的地方,会分割开,生成一个新的格子。让我们打印出来文字看看。
可以看到最后是由于页面中的",被csv文件认为是需要做切割的地方,因此,对于逗号的处理,我们要修改下操作
let array = new Array(2)
.fill(
data
// 对数字格式的字符串做处理
.map(string => !!parseInt(string) ? `\t${string}` : string)
// 对逗号以及json做处理
.map(string => string === null ? '' : "\"" + string.replaceAll("\"", "\"\"") + "\"")
);
打印出来的文字如下
生成的文件如下:
完美,游戏结束,最后的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="download">下载</button>
</body>
<script>
const downloadFunction = (dataArray) => {
document.getElementById('download').onclick = function () {
var csvRows = dataArray;
var csvString = csvRows.join("\r\n");
var csvData = new Blob([csvString], { type: 'text/csv' });
var a = document.createElement('a');
a.href = URL.createObjectURL(csvData);
a.target = '_blank';
a.download = 'export.csv';
document.body.appendChild(a);
a.click();
}
}
let column = ["name", "age", "description", "remark"];
const data = ["mk, a coder", "000018", '{"desc1":"desc1","desc2":"desc2"}', 'the remarks is: {"remark1":"remark2","reamrk3":"remark4"}'];
let array = new Array(2)
.fill(
data
// 对数字格式的字符串做处理
.map(string => !!parseInt(string) ? `\t${string}` : string)
// 对逗号以及json做处理
.map(string => string === null ? '' : "\"" + string.replaceAll("\"", "\"\"") + "\"")
);
console.log(array);
downloadFunction([column, ...array]);
</script>
</html>
当然,我的建议是能使用xlsx就使用xlsx