最近經(jīng)常在做 不規(guī)則
Excel
的導(dǎo)入,或者一些普通Excel
的導(dǎo)出,當前以上說的都是純前端來實現(xiàn);下面我們來聊聊經(jīng)常用到的Excel導(dǎo)出與導(dǎo)入的實現(xiàn)方案,本文實現(xiàn)技術(shù)棧以 Vue2 + JS 為例
導(dǎo)入分類:
- 調(diào)用
API
完全由后端來解析數(shù)據(jù),清洗數(shù)據(jù),前端只負責調(diào)用API
;- 前端解析
Excel
,清洗數(shù)據(jù),把對應(yīng)的數(shù)據(jù)處理成API
需要的 JSON;(本文主要介紹這個)
導(dǎo)出分類:
- 調(diào)用
API
完全由后端來生成Excel
,前端獲得API
返回的文件名,下載即可;- 前端根據(jù) JSON 數(shù)據(jù)來生成
Excel
, 然后利用第三方庫file-saver
進行下載;(本文主要介紹這個)
導(dǎo)入 Excel
需要用到 xlsx
這個 npm 庫
導(dǎo)出 Excel
需要用到 exceljs
, file-saver
這兩個
直接 npm install 對應(yīng)庫即可;
1. 導(dǎo)入Excel,處理數(shù)據(jù)
1.1 需求示例
假如我現(xiàn)在有一個這種 Excel 需要導(dǎo)入,前端負責解析 Excel,清洗數(shù)據(jù),API 只需要 4-5 個有用的字段
1.2 具體實現(xiàn) – html 部分
<section>
<el-button @click="handleUpload" size="mini" type="primary">{{l("ChooseFile")}}</el-button>
<input v-show="false" @change="handleFileChange" ref="inputFile" type="file" />
<el-alert type="warning" :closable="false" style="margin-top:6px;">
{{'Please Upload (xls | xlsx) Type File'}}
</el-alert>
</section>
import XLSX from "xlsx";
handleUpload() {
if (!this.importResult) {
this.$refs["inputFile"].click();
}
},
handleFileChange(e) {
const file = e.target.files[0];
const fileName = file.name.substring(file.name.lastIndexOf(".") + 1);
if (fileName !== "xlsx" && fileName !== "xls") {
this.$message.error(this.l("FileTypeError,PleaseTryAgain"));
return;
}
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = (e) => {
const result = e.target.result;
if (!result) {
this.errorMsg = this.l("NoData");
this.step = 1;
return;
}
if (this.importType === 1) {
this.handleSinglePageExcel(result);
} else {
this.handleMultiplePageExcel(result);
}
};
reader.onerror = (err) => {
throw new Error("UpLoadError: " + err.stack);
};
},
1.3 具體實現(xiàn) – 單個 sheet
handleSinglePageExcel(data) {
const wb = XLSX.read(data, {
type: "binary",
cellDates: true,
});
const sheet = wb.SheetNames[0];
const importData = XLSX.utils.sheet_to_json(wb.Sheets[sheet], {
range: -1,
});
const arr = [];
for (let i = 3; i < importData.length; i++) {
// 處理業(yè)務(wù)邏輯
}
this.importResult = arr;
},
1.4 具體實現(xiàn) – 多個 sheet
handleMultiplePageExcel(data) {
const wb = XLSX.read(data, {
type: "binary",
cellDates: true,
});
const sheetList = wb.SheetNames;
const arrMap = {}; // 多 Sheet 頁數(shù)據(jù);
sheetList.forEach((t) => {
const importData = XLSX.utils.sheet_to_json(wb.Sheets[t], {
range: 2,
});
arrMap[t] = importData;
});
const arr = [];
for (let t in arrMap) {
const importData = arrMap[t];
// importData : 代表每個 Sheet 頁的 Excel 數(shù)據(jù)
}
this.importResult = arr;
},
1.4 相關(guān)參數(shù)
文件讀取類型
類型 | 預(yù)期輸入 |
---|---|
base64 | Base64編碼類型字符串 |
binary | 二進制字符串(字節(jié)n是data.charCodeAt(n)) |
string | JS字符串(僅適用于UTF-8文本格式) |
buffer | nodejs的buffer類型 |
array | 數(shù)組 |
file | 將被讀取的文件路徑(僅限nodejs) |
常用方法
-
sheet_to_*
函數(shù)接受一個工作表和一個可選的options對象,主要是將excel文件轉(zhuǎn)化為對應(yīng)的數(shù)據(jù)格式,一般導(dǎo)入excel文件的時候使用 -
*_to_sheet
函數(shù)接受一個數(shù)據(jù)對象和一個可選的options對象,主要是將數(shù)據(jù)格式轉(zhuǎn)化為excel文件,一般導(dǎo)出文件的時候使用 -
sheet_add_*
函數(shù)接受工作表、數(shù)據(jù)和可選選項。主要用途是更新一個現(xiàn)有的工作表對象
2. 根據(jù)已有數(shù)據(jù),按需導(dǎo)出Excel
1.1 需求示例
假如我現(xiàn)在有一個這種查詢表格需要導(dǎo)出,因為所有的數(shù)據(jù)都在表格中,所以不需要調(diào)用
API
也可以實現(xiàn)文章來源:http://www.zghlxwxcb.cn/news/detail-696981.html
1.2 具體實現(xiàn)
import { Workbook } from "exceljs";
import { saveAs } from "file-saver";
try {
this.loading = true;
// 創(chuàng)建一個工作簿
const workbook = new Workbook();
// columns 需要生成的Excel列 { prop, label, width, sheetName | Detail }
// sheetName 需要生成的 Sheet 頁, 如果只生成一個 Sheet Excel 不用考慮這里
const sheets = _.uniq(this.columns.map((t) => t.sheetName || "Detail"));
for (let i = 0; i < sheets.length; i++) {
const columns = this.columns.filter(
(t) => (t.sheetName || "Detail") === sheets[i]
);
// addWorksheet 添加一個 Sheet 頁
const worksheet = workbook.addWorksheet(sheets[i]);
worksheet.columns = columns.map((t) => {
// 需求處理
const label = t.label ? t.label : this.propToLabel(t.prop);
return {
header: this.l(label), // Excel 第一行標題
key: t.prop,
width: label.length * 2, // Excel 列的寬度
};
});
// this.list -> 當前 table 數(shù)據(jù)
this.list.forEach((t) => {
const row = [];
columns.forEach((x) => {
row.push(t[x.prop] || "");
});
// 生成的 Excel Sheet 添加數(shù)據(jù)
worksheet.addRow(row);
});
// 第一行 Header 行添加自定義樣式
worksheet.getRow(1).eachCell((cell, colNumber) => {
cell.fill = {
type: "pattern",
pattern: "solid",
fgColor: {
argb: "cccccc",
},
bgColor: {
argb: "#96C8FB",
},
};
});
}
// 導(dǎo)出的文件名
const code = this.exportTemple.code || new Date().getTime();
workbook.xlsx.writeBuffer().then((buffer) => {
// 調(diào)用 第三方庫 下載剛生成好的Excel
saveAs(
new Blob([buffer], {
type: "application/octet-stream",
}),
code + "." + "xlsx"
);
this.loading = false;
});
} catch (e) {
console.error("clinet export error", e);
} finally {
this.loading = false;
}
如果
大數(shù)據(jù)的量導(dǎo)出
建議還是后端來實現(xiàn),前端要用websocket
做優(yōu)化,避免長時間 loading 帶來不好的用戶體驗文章來源地址http://www.zghlxwxcb.cn/news/detail-696981.html
到了這里,關(guān)于純前端實現(xiàn) 導(dǎo)入 與 導(dǎo)出 Excel的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!