在前端开发中,处理 Excel 文件是特别常见的任务,尤其是在一些后台管理业务中会经常涉及到数据的导入和导出等。本文将介绍如何使用 xlsx 和 file-saver 这两个库来实现前端的 Excel 数据导入与导出。xlsx 允许我们读取和创建 Excel 文件,而 file-saver 使得将文件保存到本地变得简单。
1.使用xlsx和file-saver完成导出excel功能
// 导入第三方包 import xlsx from 'xlsx' import fs from 'file-saver' xlsx(json, fields, filename = '.xlsx') { // 遍历json数据,并根据fields映射修改字段名 json.forEach(item => { for (const i in item) { if (fields.hasOwnProperty(i)) { item[fields[i]] = item[i]; // 将旧字段名的值赋给新字段名 } delete item[i]; // 删除旧字段名 } }); const sheetName = filename; // 设置Excel文件的名称 const wb = xlsx.utils.book_new(); // 创建一个新的工作簿对象 const ws = xlsx.utils.json_to_sheet(json, { header: Object.values(fields) }); // 将处理后的JSON数据转换为工作表 wb.SheetNames.push(sheetName); // 将工作表名称添加到工作簿的SheetNames数组 wb.Sheets[sheetName] = ws; // 将工作表添加到工作簿 // 设置默认单元格样式 const defaultCellStyle = { font: { name: 'Verdana', sz: 13, color: 'FF00FF88' }, fill: { fgColor: { rgb: 'FFFFAA00' }} }; // 写入选项,包括样式配置 const wopts = { bookType: 'xlsx', bookSST: false, type: 'binary', cellStyles: true, defaultCellStyle: defaultCellStyle, showGridLines: false }; // 生成Excel文件的二进制数据 const wbout = xlsx.write(wb, wopts); // 将二进制数据转换为Blob对象 const blob = new Blob([this.s2ab(wbout)], { type: 'application/octet-stream' }); // 使用file-saver库保存文件 fs.saveAs(blob, filename + '.xlsx'); }, s2ab(s) { let buf; if (typeof ArrayBuffer !== 'undefined') { // 如果支持ArrayBuffer,将字符串转换为ArrayBuffer buf = new ArrayBuffer(s.length); const view = new Uint8Array(buf); for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff; return buf; } else { // 如果不支持ArrayBuffer,使用数组 buf = new Array(s.length); for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF; return buf; } }
2.在点击事件中触发导出事件
<button @click="ImportData">导出</button> switchExportData (data) { const exportData = JSON.parse(JSON.stringify(data)) // 这里可以对数据进行一次加工,转换为用户需要的最终形式 return exportData }, ExportData (data = []) { const columns={name:'姓名',age:'年龄',sex:'性别'} // json 数据 的 key => value 对应关系 const exportData = this.switchExportData(data) // 处理数据 this.xlsx(exportData, columns, 'excel表名' ) },
3.导入功能
/* 读取文件 将文件转换为二进制 */ readFile (file) { return new Promise(resolve => { const reader = new FileReader() reader.readAsBinaryString(file) reader.onload = ev => { resolve(ev.target.result) } }) }, addHoursToDate(dateStr, hoursToAdd) { // 解析日期字符串为 Date 对象 const date = new Date(dateStr); // 添加小时 date.setHours(date.getHours() + hoursToAdd); // 格式化为 'YYYY-MM-DD' 格式 const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,+1 const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; }, switchObj (data, originalObj) { data.forEach(item => { const obj = {} for (const key in originalObj) { // 对日期格式的数据做兼容处理 if (item[originalObj[key]] instanceof Date) { obj[key] = this.addHoursToDate(item[originalObj[key]]),8) || '' // 加八小时是为了校准时差 } else { obj[key] = String(item[originalObj[key]] || '') // 将其他比如数字类型的数据统一转换成字符串类型 } } result.push(obj) }) return result }, handleUploadChange (file) { const dataBinary = await this.readFile(file.target.files[0]) // file.target.files[0]即为文件对象 file.target.value = null // 注意上传后要将input的值设为空 const workBook = xlsx.read(dataBinary, { type: 'binary', cellDates: true }) const workSheet = workBook.Sheets[workBook.SheetNames[0]] const data = xlsx.utils.sheet_to_json(workSheet) // 拿到的数据原始值,key值为中文 const columns={name:'姓名',age:'年龄',sex:'性别'} // json 数据 的 key => value 对应关系 let importData = this.switchObj(data, columns) // 将key和value转换为接口所需要的形式
4.button和input触发上传事件
<button @click="ImportData">导入</button> <input ref="file" type="file" name="file" accept=".xlsx,.xls" @change="handleUploadChange"> Importdata () { this.$refs.file.click() }