前言
相信很多前端小伙伴在开发后台管理系统的时候都会遇到这样的需求,上传或者下载 excel 表格;为什么会出现这样的需求呀,因为我们知道后台管理系统中莫非功能就是查看,删除,修改,添加,但是所谓的添加只是用于突然来了一个新员工,我们需要为其开通一个新的管理系统账号,这倒无所谓,但是如果像是一下来了很多员工呢?这个时候一个一个去填,就会大大降低效率,因此我们很多时候可以发现,让员工去填写 excel 表格,管理员只需要拿到统计好的员工表格,导入一下就可以批量添加,是不是很方便;另一种情况,我们需要拿到目前员工的所以数据表格,这个时候就需要进行导出了,因此就有了 excel 表格的上传和下载;好了,说了这么多,我们也正式看一看如何实现。
准备
首先我们需要先下载对应操作 excel 表格的包
npm install xlsx
创建一个文件,命名为 excel.js;我们将下方代码复制到这个 js 文件里面,无需过多关心里面的代码,因为已经封装好了;我们可以看到向外面暴露了两个方法,分别为 downloadExcel(导出excel)和 uploadExcel(导入excel),这两个方法就是我们所需要的,接下来往下让我们看看如何进行使用
import * as XLSX from "xlsx";
// 导出excel
export const downloadExcel = (excelData, keyName, fileName) => {
const download = (json, fileName) => {
const type = "xlsx"; //定义导出文件的格式
var tmpDown; //导出的内容
var tmpdata = json[0];
json.unshift({});
var keyMap = []; //获取keys
for (var k in tmpdata) {
keyMap.push(k);
json[0][k] = k;
}
var tmpdata = []; //用来保存转换好的json
json.map((v, i) =>
keyMap.map((k, j) =>
Object.assign(
{},
{
v: v[k],
position:
(j > 25 ? getCharCol(j) : String.fromCharCode(65 + j)) +
(i + 1),
}
)
)
)
.reduce((prev, next) => prev.concat(next))
.forEach(
(v, i) =>
(tmpdata[v.position] = {
v: v.v,
})
);
var outputPos = Object.keys(tmpdata); //设置区域,比如表格从A1到D10
var tmpWB = {
SheetNames: ["mySheet"], //保存的表标题
Sheets: {
mySheet: Object.assign(
{},
tmpdata, //内容
{
"!ref":
outputPos[0] + ":" + outputPos[outputPos.length - 1], //设置填充区域
}
),
},
};
tmpDown = new Blob(
[
s2ab(
XLSX.write(
tmpWB,
{
bookType: type == undefined ? "xlsx" : type,
bookSST: false,
type: "binary",
} //这里的数据是用来定义导出的格式类型
)
),
],
{
type: "",
}
); //创建二进制对象写入转换好的字节流
saveAs(tmpDown, fileName);
};
function saveAs(obj, fileName) {
//导出功能实现
var tmpa = document.createElement("a");
tmpa.download = fileName || "下载";
tmpa.href = URL.createObjectURL(obj); //绑定a标签
tmpa.click(); //模拟点击实现下载
setTimeout(function () {
//延时释放
URL.revokeObjectURL(obj); //用URL.revokeObjectURL()来释放这个object URL
}, 100);
}
function s2ab(s) {
//字符串转字符流
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
return buf;
}
function getCharCol(n) {
let temCol = "",
s = "",
m = 0;
while (n > 0) {
m = (n % 26) + 1;
s = String.fromCharCode(m + 64) + s;
n = (n - m) / 26;
}
return s;
}
// 这里为了不影响项目的数据的使用,使用ES6的展开运算符进行拷贝
let datas = [...excelData];
let json = datas.map((item) => {
// 遍历用户传递过来的键名,并且拿到当前数据
let returnJson = {}
for (let key in keyName) {
returnJson[keyName[key]] = item[key]
}
// 进行返回
return returnJson
});
// 导出的文件名
download(json, `${fileName}.xlsx`);
};
// 导入excel
export const uploadExcel = async (file, keyName, isOneList = true) => {
let promise = new Promise((resolve, reject) => {
// 获取上传的文件对象
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) {
// esline-disable-next-line
if (workbook.Sheets.hasOwnProperty(sheet)) {
// 利用 sheet_to_json 方法将 excel 转成 json 数据
data = data.concat(
XLSX.utils.sheet_to_json(workbook.Sheets[sheet])
);
// 如歌isOneList为true那么只取第一张表
if (isOneList) {
break;
}
}
}
// 最终获取到并且格式化后的 json 数据
const uploadData = data.map((item) => {
// 遍历用户传递过来的键名,并且拿到当前数据
let returnJson = {}
for (let key in keyName) {
returnJson[key] = item[keyName[key]]
}
// 进行返回
return returnJson
});
resolve({
code: 200,
uploadData,
message: '上传成功'
})
} catch (e) {
reject({
code: 400,
uploadData: [],
message: '上传失败'
})
}
};
// 以二进制方式打开文件
fileReader.readAsBinaryString(files[0]);
})
return promise
};
注意事项
在使用之前所注意的事项,excel 表格导入时候格式必须为以下图片格式;所导出的格式也会是以下格式
导入Excel表格
file 是文件,keyName 为键名表,true/false 决定是否只取第一张表,默认true;所返回的是一个 promise,使用 input 的 file 文件上传即可
import { uploadExcel } from "./excel.js"
uploadExcel(file, keyName, true).then((res) => {
console.log(res);
});
例如:
let keyName = {
unit: "单位",
name: "姓名",
id: "身份证号码",
phone: "手机号码",
card: "银行卡号码"
};
uploadExcel(file, keyName, true).then((res) => {
console.log(res);
});
当上传成功之后就可以拿到对应的 json 数据,此时我们请求接口添加即可
导出Excel表格
导入 excel 表格之后,接下来我们学习怎么进行导出;使用对应的 downloadExcel 方法进行导出即可,excelData 为数据,keyName 为键名表,fileName 为文件名
import { downloadExcel } from "./excel.js"
downloadExcel(excelData, keyName, fileName)
例如:
let excelData = [
{
unit: "XX科技",
name: "张三",
id:"130431718926746726",
phone: "17616728942",
card: "6217087420024872654"
},
{
unit: "XX集团",
name: "李四",
id: "130276167829747812",
phone: "18369261847",
card: "6215342891840358286"
},
];
let keyName = {
unit: "单位",
name: "姓名",
id: "身份证号码",
phone: "手机号码",
card: "银行卡号码"
};
downloadExcel(excelData, keyName, "人员信息");
结尾
好了,到这里,excel 表格的导入和导出就介绍完毕了,为什么在导入文件的时候需要 promise,因为读取文件需要时间,自己也是在封装这个方法的时候一直返回为空,只能使用 promise 进行读取完毕之后返回数据,因此就返回的是一个 promise 对象,小伙伴也可以去试试,如果对你有帮助,不妨点个赞收藏关注一下,之后还会分享更多自己的心得,如果有不懂的也可以私信或者留言。