前端 读取/导入 Excel文档

最凶残的小海豹 2024-06-24 17:33:01 阅读 77

情况: 需要通过Excel表,将数据导入到数据库,但是后台人员出差了,我又只会PHP,没用过node,所以只能前端导入Excel文件,然后循环调用后台的单条添加接口了。

库: Excel.js(版本4.3.0)

CDN地址:

<script src="https://cdn.bootcdn.net/ajax/libs/exceljs/4.3.0/exceljs.min.js"></script>

Excel.js 中文文档:https://gitee.com/alan_scut/exceljs

下面是动态Excel表单

在这里插入图片描述

下面是file文件(Excel文件)获取到的对象:

在这里插入图片描述

下面是代码中输出的需要插入的数据

在这里插入图片描述

代码:

使用方法: importExcal()

// 全局函数执行完成后执行组件的钩子函数、组件事件、自定义事件// 导入Excel表async function importExcal() { // 文件内容 (这里是从input file里面获取到的内容) var file = input_file; // 提交后端数据的整体数组 var data_arr = []; // 行程的最大列数(包含前面不变的) var stay_col_num = 0; if (file) { // 判断文件类型 let filetype = file.name.split('.')[file.name.split('.').length - 1] let filetypes = '.xlsx,.xls' if (filetypes.indexOf(filetype) === -1) { this.$message({ message: '请上传 .xlsx 或 .xls 文件。',type: 'warning'}) return; } // 读取文件文件 const reader = new FileReader(); // file.raw是具体的文件内容,需要看一下你获取到的是file.raw,还是file[0]即可 将文件转为 ArrayBuffer 格式 console.log("这里是获取到的file文件内容:", file) // 这里要用 readAsArrayBuffer 转成buffer,因为下面读取要用到 buffer 才可以 reader.readAsArrayBuffer(file.raw); reader.onload = function (event) { try { const result = event.target.result; var workbook = new ExcelJS.Workbook(); // 读取 buffer 内容 workbook.xlsx.load(result) .then(async function () { // 迭代所有sheet (如果只有一个,可以通过名称获取 var worksheet = workbook.getWorksheet('My Sheet');) workbook.eachSheet(async function (worksheet, sheetId) { // 清空数据数组 data_arr = []; // 获取 形成安排 的列数(从第8列开始的), 总不会超过100天,所以写个100 // 在这里获取 形成列的长度,是因为这里是表头,不会像内容一样出现空白单元格,造成无法获取到最终列的情况 for (let j = 8; j <= 100; j++) { // 当列到 行程安排 且,j+1 不是 行程安排的时候,就是行程安排的列宽 if (worksheet.getCell(`${ getLetter(j)}2`).value == '行程安排' && worksheet.getCell(`${ getLetter(j + 1)}2`).value !== '行程安排') { stay_col_num = j; // 如果两个都有值的话,就跳出循环 break; } } // 迭代工作表中具有值的所有行 worksheet.eachRow(function (row, rowNumber) { // 数据是从第四行开始 if (rowNumber >= 4) { // data_arr.push(row.values) // 每行的数据 let row_data = row.values; // 传给后端的对象 let data_obj = { "guest": "", "name": "", "sex": "", "company": "", "job": "", "phone": "", "stay": [] } // 循环每行的数据 row_data.map(function (item, index, arr) { // 如果是前7列,则是固定列的值,直接复制即可,否则的话则是 动态的行程安排 if (index <= 7) { switch (index) { case 2: // 嘉宾类别 data_obj.guest = item ? item : ""; break; case 3: // 姓名 data_obj.name = item ? item : ""; break; case 4: // 性别 data_obj.sex = item ? item : ""; break; case 5: // 单位 data_obj.company = item ? item : ""; break; case 6: // 职务 data_obj.job = item ? item : ""; break; case 7: // 手机号 data_obj.phone = item ? item : ""; break; } } else { // 行程安排(从第八列开始到形成的最后一列结束) if (index >= 8 && index <= stay_col_num) { if (worksheet.getCell(`${ getLetter(index)}${ rowNumber}`).value == '是') data_obj.stay.push(worksheet.getCell(`${ getLetter(index)}3`).value); } } }) // 将插入后台的数据添加进数组 data_arr.push(data_obj); } }); console.log("全部需要插入数据库的数据的数组:", data_arr) // 这里使用了 Promise 解决在for循环内,使异步接口,进行同步提交的问题;文章后面有详细说明 for (let i = 0; i < data_arr.length; i++) { let result_data = await createUser(data_arr[i]); if (!result_data.result) { // 如果出错,就跳出循环this.$message({ message: `第 ${ i + 1} 行数据 ${ data_arr[i].name}(${ data_arr[i].phone}),由于 ${ result_data.msg} 导入失败`,type: 'error'})// 跳出循环 break; } } }); }); } catch (err) { this.$message({ message: '读取文件错误',type: 'error'}) console.log('err', err); } }; } else { this.$message({ message: '请选择文件',type: 'error'}) }}// 添加用户信息接口async function createUser(data) { return await new Promise(function (resolve, reject) { // 处理异步逻辑时候调用resolve和reject函数 axios({ method: 'POST', url: `${ base_url}/api/add`, headers: { // 没有可以不要token // authorization: `bearer ${token}` }, // 数据 data: data }).then(res => { let resp = res.data; if (resp.code == 1) { if (resp.data.code == 200) { resolve({ "result": true }); } } else { resolve({ "result": false, "msg": resp.msg }); } }).catch(req => { reject({ "result": false, "msg": "" }); }); });}// 获取第N个字母function getLetter(num) { return String.fromCharCode(64 + num);}

代码中用到的方法总结:

新建工作簿

var workbook = new ExcelJS.Workbook();

读取 buffer 内容

workbook.xlsx.load(data).then(function() {

// 其他代码

});

迭代所有sheet

workbook.eachSheet(function(worksheet, sheetId) {

// 其他代码

});

按名称获取表格

var worksheet = workbook.getWorksheet(‘My Sheet’);

按ID获取表格

var worksheet = workbook.getWorksheet(1);

迭代工作表中具有值的所有行

worksheet.eachRow(function(row, rowNumber) {

console.log(‘Row:’ + rowNumber + ’ = ’ + JSON.stringify(row.values));

});

获取单元格(A2)

var collectcell = worksheet.getCell(‘A2’);

获取当前worksheet的最后一个单元格信息

var lastRowCell = worksheet.lastRow;

console.log(‘最后一行行数:’ + lastRowCell.number);

for循环内,使异步接口变成同步提交

我文章的地址:前端JS for循环内异步接口变成同步提交(JavaScript for循环异步变同步)

遇见的一些问题:

1. Excel.JS 支持的数据读取方式不同,获取的数据类型不同。例如:filestreambuffer

另外说一下

有兴趣的朋友也可以试试 SheetJS ,感觉好像功能更多一些,下次我再需要用到excel的时候也会尝试一下的。

SheetJS中文文档:https://github.com/rockboom/SheetJS-docs-zh-CN

尝试完成,回来记录一下: SheetJS 文档会更丰富一些,但是他分社区版(免费)和专业版(收费)。社区版不支持导出文件的样式修改,专业版才可以。

我决定还是继续用 Excel.js



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。