JavaScript實現(xiàn)excel文件導入導出
一、需求場景描述
文件的導入導出是非常常見的需求功能,excel文件的導入導出更為常見,實踐中許多時候,是調用接口實現(xiàn)導入導出的,也就是說將文件導入導出的邏輯交給后端去做了。但是,有的時候確也需要前端自行實現(xiàn)導入導出,此時前端實現(xiàn)導入導出可能是更好的選擇。
1.此時前端上傳解析excel文件可能更合適
例如,一個常規(guī)excel文件填寫模板,在用戶的電腦上,用戶上傳完后,還可以在預覽展示時,在線修改,改完可以下載,也可以將數(shù)據給到服務端,但這時,比如這模板數(shù)據通常不多,比如是一個團隊成員這樣的數(shù)據,通過文件流的形式傳給后端,可能不是很理想,倒不如前端解析傳那幾行數(shù)據就行。
這種場景下,需要前端做到上傳并解析excel文件。
2.此時前端下載excel文件可能優(yōu)雅一些
支持用戶動態(tài)增減篩選數(shù)據的界面,由于這種頻繁的變更不是實時變更到服務器的,因此服務器其實沒有存有剛剛用戶的增減篩選的操作結果,此時由于前端主導下載可能更合適。當然,把操作的最終結果更新到服務器再告知服務器提供下載也是可行的。
這種場景下,需要前端做到過濾解析數(shù)據,然后做excel文件的下載。
實踐效果圖如下:

二、實現(xiàn)思路分析
1.導入excel文件實現(xiàn)思路分析
- 1.使用html支持上傳標簽從本地獲取文件,例如type為file的input,el-upload等。
- 2.利用FileReader將文件讀取為二進制字符串。
- 3.使用XLSX插件的XLSX.read()方法,將二進制字符串轉換成excel文件的工作蒲對象workbook(簡寫成wb)。
- 4.通過XLSX.utils.sheet_to_json()方法,從wb中獲取第一張 Sheets表格數(shù)據并將其轉換為json數(shù)據。
- 5.重組json數(shù)據生成數(shù)組,即是根據自己的定義的列字段名,重新組成符合自己需求的json數(shù)據。因為從excel中提取的數(shù)據是沒有字段名或字段名不符合要求的,
而我們需要渲染在頁面表格中又確實需要合適的字段名。
2.導出excel文件實現(xiàn)思路分析
- 1.通過XLSX插件的 XLSX.utils.book_new()方法,創(chuàng)建excel工作蒲對象wb。
- 2.按需插入第一行數(shù)據,通過數(shù)組的unshift()方法。
- 3.通過XLSX.utils.json_to_sheet(),創(chuàng)建excel表格對象ws。
- 4.通過json_to_array(key,data),結合自定義的字段名key,和數(shù)據記錄data,生成新數(shù)組。
- 5.通過auto_width(),對ws和新生成的數(shù)組,自動計算各列col寬。
- 6.通過XLSX.utils.book_append_sheet(),生成實際excel工作蒲,并使用XLSX.writeFile()生成excel文件。
三、關鍵代碼
1. exportExcel.js 導出excel文件
/* eslint-disable */
/* 導出excel文件 */
/**
* 導出excel文件實現(xiàn)思路分析
*
* 1.通過XLSX插件的 XLSX.utils.book_new()方法,創(chuàng)建excel工作蒲對象wb。
* 2.按需插入第一行數(shù)據,通過數(shù)組的unshift()方法。
* 3.通過XLSX.utils.json_to_sheet(),創(chuàng)建excel表格對象ws。
* 4.通過json_to_array(key,data),結合自定義的字段名key,和數(shù)據記錄data,生成新數(shù)組。
* 5.通過auto_width(),對ws和新生成的數(shù)組,自動計算各列col寬。
* 6.通過XLSX.utils.book_append_sheet(),生成實際excel工作蒲,并使用XLSX.writeFile()生成excel文件。
*/
import XLSX from 'xlsx'
// 自動計算col列寬
function auto_width (ws, data) {
/*set worksheet max width per col*/
const colWidth = data.map(row => row.map(val => {
/*if null/undefined*/
if (val == null) {
return { 'wch': 10 }
}
/*if chinese*/
else if (val.toString().charCodeAt(0) > 255) {
return { 'wch': val.toString().length * 2 }
} else {
return { 'wch': val.toString().length }
}
}))
/*start in the first row*/
let result = colWidth[0]
for (let i = 1; i < colWidth.length; i++) {
for (let j = 0; j < colWidth[i].length; j++) {
if (result[j]['wch'] < colWidth[i][j]['wch']) {
result[j]['wch'] = colWidth[i][j]['wch']
}
}
}
ws['!cols'] = result
}
// 將json數(shù)據轉換成數(shù)組
function json_to_array (key, jsonData) {
return jsonData.map(v => key.map(j => {
return v[j]
}))
}
/**
* @param header Object,表頭
* @param data Array,表體數(shù)據
* @param key Array,字段名
* @param title String,標題(會居中顯示),即excel表格第一行
* @param filename String,文件名
* @param autoWidth Boolean,是否自動根據key自定義列寬度
*/
export const exportJsonToExcel = ({
header,
data,
key,
title,
filename,
autoWidth
}) => {
const wb = XLSX.utils.book_new()
if (header) {
data.unshift(header)
}
if (title) {
data.unshift(title)
}
const ws = XLSX.utils.json_to_sheet(data, {
header: key,
skipHeader: true
})
if (autoWidth) {
const arr = json_to_array(key, data)
auto_width(ws, arr)
}
XLSX.utils.book_append_sheet(wb, ws, filename)
XLSX.writeFile(wb, filename + '.xlsx')
}
export default {
exportJsonToExcel
}2. importExcel.js 導入excel文件
/* eslint-disable */
/* 導入excel文件 */
/**
* 導入excel文件實現(xiàn)思路分析
*
* 1.使用html支持上傳標簽從本地獲取文件,例如type為file的input,el-upload等。
* 2.利用FileReader將文件讀取為二進制字符串。
* 3.使用XLSX插件的XLSX.read()方法,將二進制字符串轉換成excel文件的工作蒲對象workbook(簡寫成wb)。
* 4.通過XLSX.utils.sheet_to_json()方法,從wb中獲取第一張 Sheets表格數(shù)據并將其轉換為json數(shù)據。
* 5.重組json數(shù)據生成數(shù)組,即是根據自己的定義的列字段名,重新組成符合自己需求的json數(shù)據。因為從excel中提取的數(shù)據是沒有字段名或字段名不符合要求的,
* 而我們需要渲染在頁面表格中又確實需要合適的字段名。
*/
/**
* @param file 文件流
* @param tableTemplate 要導入的表格模板,一個數(shù)組,如:
* tableTemplate: ['userCode', 'userName', 'department', 'major', 'position'],其中的值
* 為表格的字段名,注意字段的順序應與實際的導入excel一致。
*/
export default function importExcel (file, tableTemplate) {
return new Promise((resolve, reject) => {
let f = file.raw // 獲取文件內容
// 通過DOM取文件數(shù)據
let rABS = false // 是否將文件讀取為二進制字符串
let reader = new FileReader()
FileReader.prototype.readAsBinaryString = function (f) {
let binary = ''
let rABS = false // 是否將文件讀取為二進制字符串
let wb // 讀取完成的數(shù)據
let outdata
let reader = new FileReader()
reader.onload = function (e) {
let bytes = new Uint8Array(reader.result)
let length = bytes.byteLength
for (let i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i])
}
let XLSX = require('xlsx')
if (rABS) {
wb = XLSX.read(btoa(binary), { // 手動轉化
type: 'base64'
})
} else {
wb = XLSX.read(binary, {
type: 'binary'
})
}
outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]) // outdata就是表格中的值
let arr = []
// 下面是數(shù)據解析提取邏輯
if (tableTemplate.length > 0) {
let tempArr = Object.keys(outdata[0])
let tempArrNew = []
for (let i in tempArr) {
for (let k in tableTemplate) {
if (i === k) {
tempArrNew.push({fieldE: tableTemplate[k], fieldC: tempArr[i]})
}
}
}
tempArr = tempArrNew
outdata.map(item => {
let obj = {}
tempArr.map(temp2 => {
obj[temp2.fieldE] = item[temp2.fieldC]
})
arr.push(obj)
})
}
resolve(arr)
}
reader.readAsArrayBuffer(f)
}
if (rABS) {
reader.readAsArrayBuffer(f)
} else {
reader.readAsBinaryString(f)
}
})
}四、使用示例
1.使用示例一:上傳解析excel
關鍵 html 代碼部分
<el-upload
action=""
id="upload-excel"
:on-change="handleChange"
:show-file-list="false"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
:auto-upload="false">
</el-upload>
<el-table
class="cn-table-th-bg"
size="small"
:data="tableData"
border
style="width: 100%">
<el-table-column type="index" label="序號" width="50" align="center"></el-table-column>
<el-table-column prop="userSource" label="來源" align="center"></el-table-column>
<el-table-column prop="userCode" label="工號" align="center"></el-table-column>
<el-table-column prop="userName" label="姓名" align="center"></el-table-column>
<el-table-column prop="department" label="部門" align="center"></el-table-column>
<el-table-column prop="major" label="專業(yè)" align="center"></el-table-column>
<el-table-column prop="position" label="職務/職稱" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button @click="clickDelete(scope.row)" size="mini">刪除</el-button>
<el-button @click="moveUp(tableData,scope.$index)" size="mini" class="up-button">上移</el-button>
<el-button @click="moveDown(tableData,scope.$index)" size="mini" class="down-button">下移</el-button>
</template>
</el-table-column>
</el-table>// 關鍵 js 代碼部分
import importExcel from '@/utils/excel/importExcel'
handleChange (file, fileList) {
tableField: ['userCode', 'userName', 'department', 'major', 'position'],
importExcel(file, tableField).then(res => {
this.tableData = res
})
}2.使用示例二:下載excel文件
關鍵 js 代碼
import { exportJsonToExcel } from '@/utils/excel/exportExcel'
clickDownload () {
const tableField = ['userCode', 'userName', 'department', 'major', 'position'],
tableHeader = {userCode: '工號', userName: '姓名', department: '部門', major: '專業(yè)', position: '職位/職稱'},
tableTitle = '導出表格',
templateData = [
{'userCode': 'N1001', 'userName': '張三', 'department': '綜合管理部', 'major': '計算機科學與技術', 'position': '項目經理'}
],
obj = {
header: tableHeader,
data: templateData,
key: tableField,
title: '',
filename: '團隊成員導入模板',
autoWidth: true
}
exportJsonToExcel(obj)
},到此這篇關于JavaScript實現(xiàn)excel文件導入導出的文章就介紹到這了,更多相關JS文件導入導出內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
javascript特效實現(xiàn)——當前時間和倒計時效果的簡單實例
下面小編就為大家?guī)硪黄猨avascript特效實現(xiàn)——當前時間和倒計時效果的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-07-07

