前端 读取/导入 Excel文档

avatar
作者
筋斗云
阅读量:0

情况: 需要通过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

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!