前言
這是一個(gè)常用的功能,就是導(dǎo)入和導(dǎo)出excel表格
但是時(shí)常會(huì)遇到一些復(fù)雜表頭的表格導(dǎo)出和導(dǎo)入
比如我這個(gè)案例里面的三層表頭的表格。
網(wǎng)上看了下發(fā)現(xiàn)了一個(gè)非常簡(jiǎn)單導(dǎo)出和導(dǎo)入方法
當(dāng)然這個(gè)是純前端的版本,會(huì)出現(xiàn)分頁不好下載的情況。所以實(shí)際工作中,導(dǎo)出還是后端負(fù)責(zé)的。
效果圖
這里是表格的樣式,三層表頭
?這里是點(diǎn)擊導(dǎo)出后的效果和表格格式
?
這里是點(diǎn)擊導(dǎo)入后的效果和獲取的數(shù)據(jù)格式
?使用方法簡(jiǎn)介
1,要下載一個(gè)插件,輸入這個(gè)指令:npm install -S?file-saver?xlsx
2,在頁面中引入這個(gè),直接在你需要寫導(dǎo)入導(dǎo)出的表格頁面寫就行
3,給你的表格綁上這個(gè)id。用來導(dǎo)出的時(shí)候拿數(shù)據(jù)的
?
這里如果想要導(dǎo)入后獲取數(shù)據(jù)傳給后端,就在這個(gè)位置把他循環(huán)push到一個(gè)新數(shù)組內(nèi),然后在循環(huán)外面把這個(gè)數(shù)組傳給后端
?代碼部分(純前端導(dǎo)入導(dǎo)出)
<template>
<div>
<div class="titleBtn">
<!-- 導(dǎo)出Excel -->
<el-button
@click="exportClick"
type="primary"
size="small"
style="margin: 0 20px"
icon="el-icon-folder-opened"
>導(dǎo)出</el-button
>
<!-- 導(dǎo)入Excel -->
<el-upload
action="/上傳文件的接口"
:on-change="onChange"
:auto-upload="false"
:show-file-list="false"
accept=".xls, .xlsx"
ref="upload"
:multiple="true"
>
<el-button type="warning" icon="el-icon-folder-add" size="small"
>導(dǎo)入</el-button
>
</el-upload>
</div>
<el-table :data="tableData" style="width: 100%" id="mainTable">
<el-table-column prop="date" label="日期" width="150"> </el-table-column>
<el-table-column label="配送信息">
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column label="地址">
<el-table-column prop="province" label="省份" width="120">
</el-table-column>
<el-table-column prop="city" label="市區(qū)" width="120">
</el-table-column>
<el-table-column prop="address" label="地址" width="300">
</el-table-column>
<el-table-column prop="zip" label="郵編" width="120">
</el-table-column>
</el-table-column>
</el-table-column>
</el-table>
</div>
</template>
<script>
import FileSaver from "file-saver";
import * as XLSX from "xlsx";
export default {
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
province: "上海",
city: "普陀區(qū)",
address: "上海市普陀區(qū)金沙江路 1518 弄",
zip: 200333,
},
],
};
},
methods: {
//導(dǎo)出
exportClick() {
//第一個(gè)參數(shù)是到處后文件名,第二個(gè)是id綁定表格dom
this.exportExcel("test", "mainTable");
},
//轉(zhuǎn)換數(shù)據(jù)
exportExcel(filename, tableId) {
var xlsxParam = { raw: true }; // 導(dǎo)出的內(nèi)容只做解析,不進(jìn)行格式轉(zhuǎn)換
var table = document.querySelector("#" + tableId).cloneNode(true);
var wb = XLSX.utils.table_to_book(table, xlsxParam);
/* 獲取二進(jìn)制字符進(jìn)行輸出 */
var wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array",
});
try {
FileSaver.saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
filename + ".xlsx"
);
} catch (e) {
if (typeof console !== "undefined") {
console.log(e, wbout);
}
}
return wbout;
},
//導(dǎo)入
onChange(file, fileList) {
this.readExcel(file); // 調(diào)用讀取數(shù)據(jù)的方法
},
// 讀取數(shù)據(jù)
readExcel(file) {
let that = this;
if (!file) {
//如果沒有文件
return false;
} else if (!/.(xls|xlsx)$/.test(file.name.toLowerCase())) {
this.$message.error("上傳格式不正確,請(qǐng)上傳xls或者xlsx格式");
return false;
}
const fileReader = new FileReader();
fileReader.onload = (ev) => {
try {
const data = ev.target.result;
const workbook = XLSX.read(data, {
type: "binary",
});
if (workbook.SheetNames.length >= 1) {
this.$message({
message: "導(dǎo)入數(shù)據(jù)表格成功",
showClose: true,
type: "success",
});
}
const wsname = workbook.SheetNames[0]; //取第一張表
const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格內(nèi)容
console.log("生成json:", ws);
// that.tableData = [];
for (var i = 2; i < ws.length; i++) {
let sheetData = {
// 鍵名為綁定 el 表格的關(guān)鍵字,值則是 ws[i][對(duì)應(yīng)表頭名]
date: ws[i]["日期"],
name: ws[i]["配送信息"],
province: ws[i]["__EMPTY"],
city: ws[i]["__EMPTY_1"],
address: ws[i]["__EMPTY_2"],
zip: ws[i]["__EMPTY_3"],
};
console.log("上傳的數(shù)據(jù):", sheetData);
//添加到表格中
that.tableData.push(sheetData);
//正常導(dǎo)入需要拿到上傳的數(shù)據(jù)就在這從新弄個(gè)數(shù)組push進(jìn)去,然后傳給后臺(tái),后臺(tái)保存后查詢表格返給前端。
}
this.$refs.upload.value = "";
} catch (e) {
console.log(e);
return false;
}
};
// 如果為原生 input 則應(yīng)是 files[0]
fileReader.readAsBinaryString(file.raw);
},
},
};
</script>
<style scoped>
.titleBtn {
display: flex;
margin: 20px 0;
}
</style>
?配合后端的兩個(gè)方法
?因?yàn)樯厦娴募兦岸藢懛ㄓ幸粋€(gè)問題,就是有分頁的時(shí)候我們沒法拿到數(shù)據(jù)。
或者數(shù)據(jù)太大了我們下載實(shí)在是有點(diǎn)慢和卡。所以基本上工作中都是后端生成下載鏈接導(dǎo)出的。
這里再分享兩個(gè)方法。
1,a標(biāo)簽下載
這種方法核心就是后端直接生成下載鏈接,前端只需要生成A標(biāo)簽然后下載就行了。較為常用的一個(gè)
daochu(){
// A標(biāo)簽導(dǎo)出方法:通過生成一個(gè)A標(biāo)簽然后觸發(fā)后臺(tái)傳過來的下載鏈接完成導(dǎo)出
//核心注意需要給請(qǐng)求的格式改為:responseType: "blob",
this.axios
.post(
url, {}, {
token: true,
responseType: "blob",
}
)
.then((res) => {
if (res.status == 200) {
//拿到后臺(tái)發(fā)過來的下載鏈接
let url = window.URL.createObjectURL(new Blob([res.data]));
//生成一個(gè)A標(biāo)簽
let link = document.createElement("a");
//樣式設(shè)為none,沒有大小,不占位置
link.style.display = "none";
//把鏈接地址給href
link.href = url;
//下載后的名字,用時(shí)間來標(biāo)注避免重復(fù)
let filename = new Date().getTime() + ".xlsx";
//給A標(biāo)簽添加屬性download,值為上面的名字
link.setAttribute("download", filename);
//在頁面的尾部插入元素A標(biāo)簽
document.body.appendChild(link);
//點(diǎn)擊A標(biāo)簽,這樣就觸發(fā)下載了。
link.click();
} else if (res.data.code != 200) {
this.$message("暫無數(shù)據(jù)");
}
this.exporloading = false;
})
.catch((err) => {
this.exporloading = false;
});
}
2,用上面的那種前端方法,我們直接讓后端傳給我們一個(gè)完整的表格數(shù)據(jù),不分頁的那種。
然后用這個(gè)數(shù)據(jù)賦值到表格的數(shù)組內(nèi),然后把表格dom拿去導(dǎo)出方法中也可以下載。
這里我是因?yàn)楹蠖藳]有給全部的數(shù)據(jù),然后數(shù)據(jù)不是很多,我就干脆自己前臺(tái)直接循環(huán)請(qǐng)求把每一頁的數(shù)據(jù)合并到數(shù)組內(nèi)實(shí)現(xiàn)了拿到所有數(shù)據(jù)的目的,不過這樣不推薦啊。
這里this.$excels是我封裝了一下這個(gè)方法,然后main.js賦值原型了。方法還是和上面的一樣哈。
封裝的樣子,和上面基本是一樣的。
這是循環(huán)拿到的分頁數(shù)據(jù),看到了吧85條都拿到了,然后復(fù)制給tableData2數(shù)組,然后拿表格的dom,就可以導(dǎo)出全部數(shù)據(jù)的表格了
表格中多個(gè)sheet一次讀取出來寫法
有時(shí)候我們需要的不僅僅是第一個(gè)sheet的。可能一個(gè)表格中有很多個(gè)sheet然后每個(gè)sheet字段不一樣。所以我們可以這樣寫,在上面的方法中稍加改動(dòng)。
只需要把readExcel這個(gè)方法修改一下就行了。修改的地方主要就是加了個(gè)循環(huán),讀取每一個(gè)sheet的數(shù)據(jù)出來。
// 讀取數(shù)據(jù)
readExcel(file) {
let that = this;
if (!file) {
//如果沒有文件
return false;
} else if (!/.(xls|xlsx)$/.test(file.name.toLowerCase())) {
this.$message.error("上傳格式不正確,請(qǐng)上傳xls或者xlsx格式");
return false;
}
const fileReader = new FileReader();
fileReader.onload = (ev) => {
try {
const data = ev.target.result;
const workbook = XLSX.read(data, {
type: "binary",
});
if (workbook.SheetNames.length >= 1) {
//讀取到表中sheet
this.$message({
message: "導(dǎo)入數(shù)據(jù)表格成功",
showClose: true,
type: "success",
});
}
for (var i = 0; i < workbook.SheetNames.length; i++) {
const wsname = workbook.SheetNames[i]; //取第一張表
const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格內(nèi)容
console.log("生成json:", ws);
// that.tableData = [];
// for (var i = 2; i < ws.length; i++) {
// let sheetData = {
// // 鍵名為綁定 el 表格的關(guān)鍵字,值則是 ws[i][對(duì)應(yīng)表頭名]
// date: ws[i]["日期"],
// name: ws[i]["配送信息"],
// province: ws[i]["__EMPTY"],
// city: ws[i]["__EMPTY_1"],
// address: ws[i]["__EMPTY_2"],
// zip: ws[i]["__EMPTY_3"],
// };
// console.log("上傳的數(shù)據(jù):", sheetData);
// //添加到表格中
// that.tableData.push(sheetData);
// //正常導(dǎo)入需要拿到上傳的數(shù)據(jù)就在這從新弄個(gè)數(shù)組push進(jìn)去,然后傳給后臺(tái),后臺(tái)保存后查詢表格返給前端。
// }
}
this.$refs.upload.value = "";//清空上傳列表,不能放在循環(huán)內(nèi)清空,否則第一次循環(huán)sheet1時(shí)直接清空了上傳列表,第二次循環(huán)sheet2就沒數(shù)據(jù)了
} catch (e) {
console.log(e);
return false;
}
};
// 如果為原生 input 則應(yīng)是 files[0]
fileReader.readAsBinaryString(file.raw);
},
多sheet讀取效果圖
文章來源:http://www.zghlxwxcb.cn/news/detail-671937.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-671937.html
到了這里,關(guān)于【vue導(dǎo)入導(dǎo)出Excel】vue簡(jiǎn)單實(shí)現(xiàn)導(dǎo)出和導(dǎo)入復(fù)雜表頭excel表格功能【純前端版本和配合后端版本】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!