一、背景
需要讲后端返回来的表格数据通过前端设置导出其中某些字段,而且得是xlsx格式的。
那就考虑使用控件SheetJS。如果是几年前,一般来说,保存excel的文件都是后端去处理,处理完成给前端一个接口,前端调用了打开就可以下载到该表格了。但是,因为PC电脑的硬件处理数据的能力越来越好,前端也具备了处理一些大数据的能力。那么处理大数据就需要把相关的情况考虑完全的控件,SheetJS就是这样的一个工具。
二、官网
API Reference | SheetJS Community Edition
三、常用的API
* XLSX.utils.aoa_to_sheet:数组转换为worksheet
* XLSX.utils.json_to_sheet:json对象转换为worksheet
* XLSX.utils.table_to_sheet:表格转换为worksheet
四、两大对象
workbook对象与worksheet对象
可以理解成,workbook对象是整个表格的内容,而worksheet可以理解成表格的数据内容。
直观点看:
fileInput.addEventListener("change", (event) => {
handleFileUpload(event.target.files[0]);
});
// 文件上传函数
function handleFileUpload(file) {
const reader = new FileReader();
reader.readAsArrayBuffer(file);
// 定义一个加载完成的回调,在 FileReader 完成文件读取操作后被调用。
reader.onload = (event) => {
const data = new Uint8Array(event.target.result);
const workbook = XLSX.read(data, { type: "array" });
console.log('workbook', workbook)
// 获取工作表名数组
const sheetNameArray = workbook.SheetNames;
// 获取第一个工作表
const firstSheet = workbook.Sheets[sheetNameArray[0]];
// 将工作表转换为二维数组
const sheetDataArray = XLSX.utils.sheet_to_json(firstSheet, {
// defval: "" // 配置这个得到对象数组的格式
header: 1 // 得到二维数组
});
// 调用渲染 Excel 的函数
renderTable(sheetDataArray);
};
}
打印的workbook如下:
显然,多个表,它也能够把它的数据抓出来。
五、上传相关
//读取(本地或网络)文件,并创建一个工作薄
let workbook = XLSX.read(data, opts);
//创建一个新的工作簿
let workbook = XLSX.utils.book_new();
//通过抓取页面中的 HTML TABLE 创建工作表
let workbook = XLSX.utils.table_to_book(dom_element, opts);
//将Array<Object>生成为sheet,其中包含基于对象键自动生成的“标题”。
//header 标题使用指定的字段顺序(默认 Object.keys)
//skipHeader 如果为true,则不会在输出中包含标题行
let worksheet = XLSX.utils.json_to_sheet(Array<Object>, {header, skipHeader: false});
//将Array<Array>生成为sheet
let worksheet = XLSX.utils.aoa_to_sheet(Array<Array>);
//接受一个表 DOM 元素并返回一个类似于输入表的工作薄
let worksheet = XLSX.utils.table_to_sheet(DOM)
//更新sheet,在对应位置进行覆盖
XLSX.utils.sheet_add_json(worksheet, Array<Object>, {header,skipHeader: true, origin: "A2"});
XLSX.utils.sheet_add_aoa(worksheet, Array<Array>, { origin: "A1" });
XLSX.utils.sheet_add_dom(worksheet, DOM, { origin: -1 });
//将sheet工作表添加到该工作薄中
XLSX.utils.book_append_sheet(workbook, worksheet, "sheet名称");
伪代码(开发过程根据自己的业务进行):
function excelImport(vv) {
const eleInput = document.createElement('input');
eleInput.type = 'file';
eleInput.style.display = 'block';
eleInput.onchange = function (e) {
const file = e.target.files[0];
let name = file.name
let suffix = name.substr(name.lastIndexOf("."));
let reader = new FileReader()
reader.onload = async (event) => {
try {
// 判断文件类型是否正确
if (".xls" != suffix && ".xlsx" != suffix) {
cb.utils.alert("选择Excel格式的文件导入!");
return false;
}
let { result } = event.target;
// 读取文件
let workbook = XLSX.read(result, { type: 'binary' });
let data = [];
// 循环文件中的每个表
let reg = /[\u4e00-\u9fa5|(|)|_$]/g;
for (let sheet in workbook.Sheets) {
if (workbook.Sheets.hasOwnProperty(sheet)) {
let str = XLSX.utils.sheet_to_json(workbook.Sheets[sheet])
sheet = sheet.replace(reg, "")
// 将获取到表中的数据转化为json格式
data = data.concat(str)
}
}
let source = data.splice(3, data.length);
insertExcellData(vv, source); //该方法是处理数据的详细方式,根据业务需要来处理。
} catch (e) {
cb.utils.alert("文件类型不正确!");
}
}
reader.readAsBinaryString(file);
document.body.removeChild(eleInput);
}
document.body.appendChild(eleInput);
eleInput.dispatchEvent(new MouseEvent('click'))
}
也可以试试直接cdn引入的方式:
<html lang="zh-CN">
<head>
<meta charset="utf-8">
</meta>
</head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.4/xlsx.full.min.js"></script>
<body>
<!-- 用于点击上传文件的输入字段 -->
<input type="file" id="fileInput" style="display: none" accept=".xls,.xlsx" required />
<label for="fileInput" class="label">点击上传文件</label>
<!-- 用于拖放文件上传的输入字段 -->
<div id="dropArea">
<p>拖拽文件至此处</p>
</div>
<!-- 用于显示解析后的数据表 -->
<div id="table-container" style="margin-top: 20px"></div>
<script>
const fileInput = document.getElementById("fileInput");
const dropArea = document.getElementById("dropArea");
fileInput.addEventListener("change", (event) => {
handleFileUpload(event.target.files[0]);
});
dropArea.addEventListener("drop", (e) => {
e.preventDefault();
dropArea.style.border = "2px dashed #ccc";
const droppedFiles = e.dataTransfer.files;
handleFileUpload(droppedFiles[0]);
});
// 文件上传函数
function handleFileUpload(file) {
const reader = new FileReader();
console.log('file', file)
reader.readAsArrayBuffer(file);
// 定义一个加载完成的回调,在 FileReader 完成文件读取操作后被调用。
reader.onload = (event) => {
console.log('event', event)
const data = new Uint8Array(event.target.result);
const workbook = XLSX.read(data, { type: "array" });
console.log('workbook', workbook)
// 获取工作表名数组
const sheetNameArray = workbook.SheetNames;
// 获取第一个工作表
const firstSheet = workbook.Sheets[sheetNameArray[0]];
// 将工作表转换为二维数组
const sheetDataArray = XLSX.utils.sheet_to_json(firstSheet, {
// defval: "" // 配置这个得到对象数组的格式
header: 1 // 得到二维数组
});
// 调用渲染 Excel 的函数
renderTable(sheetDataArray);
};
}
// 将数据渲染为一个表格
function renderTable(sheetDataArray) {
const table = document.createElement("table");
table.classList.add("table", "table-striped");
sheetDataArray.forEach((row) => {
const tableRow = document.createElement("tr");
row.forEach((cell) => {
const tableCell = document.createElement("td");
tableCell.textContent = cell;
tableRow.appendChild(tableCell);
});
table.appendChild(tableRow);
});
// 添加数据表到表格容器
const tableContainer = document.getElementById("table-container");
tableContainer.innerHTML = "";
tableContainer.appendChild(table);
}
// 为拖放添加事件监听器
dropArea.addEventListener("dragover", (e) => {
e.preventDefault();
dropArea.style.border = "2px dashed #333";
});
dropArea.addEventListener("dragleave", () => {
dropArea.style.border = "2px dashed #ccc";
});
</script>
</body>
</html>
六、下载相关
最重要的代码片段如下:
//数据
let sheet=XLSX.utils.json_to_sheet(arr),
book=XLSX.utils.book_new();
XLSX.utils.book_append_sheet(book,sheet,"sheet1");
// user开头加时间戳的文件名,可以修改成其它名字
XLSX.writeFile(book,`列表.xls`);
伪代码如下:
<div onclick="clickfn()">点击这里</div>
function clickfn() {
let arr = [
{
'序号': 1,
'名字': '张三',
'员工号码': '789'
}
]
let sheet=XLSX.utils.json_to_sheet(arr), //arr 数据需要业务上给与
book=XLSX.utils.book_new();
XLSX.utils.book_append_sheet(book,sheet,"sheet1");
// user开头加时间戳的文件名,可以修改成其它名字
XLSX.writeFile(book,`列表.xls`);
}