Récemment, je fais souvent
Excel
des importations irrégulières, ou certainesExcel
exportations courantes. À l'heure actuelle, les éléments mentionnés ci-dessus sont de pures implémentations frontales ; parlons des schémas d'implémentation de l'exportation et de l'importation Excel qui sont souvent utilisés. Cet article implémente la pile technologique avec Vue2. + JS comme exemple
Catégories d'importation :
- Appel
API
Les données sont entièrement analysées et nettoyées par le backend, et le frontend n'est responsable que de l'appelAPI
;- Le frontal analyse
Excel
, nettoie les données et traite les données correspondantes dans leAPI
JSON requis ; (cet article présente principalement ceci)
Catégories d'exportation :
- L'appel
API
est entièrement généré par le backendExcel
, et le frontend obtientAPI
le nom du fichier renvoyé et le télécharge ;- Le front-end est généré à partir de données JSON , puis téléchargé
Excel
à l'aide d'une bibliothèque tierce ; (cet article présente principalement ceci)file-saver
L'importation Excel
doit utiliser xlsx
cette bibliothèque npm
L'exportation Excel
doit être utilisée exceljs
, file-saver
ces deux-là
Npm installe simplement la bibliothèque correspondante directement ;
1. Importez Excel et traitez les données
1.1 Exemple d'exigence
Si j'ai maintenant un Excel de ce type qui doit être importé, le front-end est responsable de l'analyse d'Excel et du nettoyage des données, et l'API n'a besoin que de 4 à 5 champs utiles.
1.2 Implémentation spécifique – partie 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 Mise en œuvre spécifique – feuille unique
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++) {
// 处理业务逻辑
}
this.importResult = arr;
},
1.4 Implémentation spécifique – feuilles multiples
handleMultiplePageExcel(data) {
const wb = XLSX.read(data, {
type: "binary",
cellDates: true,
});
const sheetList = wb.SheetNames;
const arrMap = {
}; // 多 Sheet 页数据;
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 数据
}
this.importResult = arr;
},
1.4 Paramètres associés
type de lecture de fichier
taper | contribution attendue |
---|---|
base64 | Chaîne de type codée en base64 |
binaire | chaîne binaire (l'octet n est data.charCodeAt(n)) |
chaîne | Chaîne JS (uniquement pour le format de texte UTF-8) |
tampon | Le type de tampon de nodejs |
tableau | tableau |
déposer | Le chemin d'accès au fichier qui sera lu (nodejs uniquement) |
méthode commune
sheet_to_*
La fonction accepte une feuille de calcul et un objet d'options optionnel, principalement pour convertir le fichier Excel dans le format de données correspondant, généralement utilisé lors de l'importation du fichier Excel.*_to_sheet
La fonction accepte un objet de données et un objet d'options facultatif, principalement pour convertir le format de données en fichier Excel, généralement utilisé lors de l'exportation de fichiers.sheet_add_*
La fonction accepte les feuilles de calcul, les données et les options facultatives. L'objectif principal est de mettre à jour un objet de feuille de calcul existant
2. Selon les données existantes, exportez Excel selon vos besoins
1.1 Exemple d'exigence
Si j'ai maintenant une table de requêtes de ce type qui doit être exportée, car toutes les données sont dans la table, elle
API
peut être implémentée sans appeler
1.2 Mise en œuvre spécifique
import {
Workbook } from "exceljs";
import {
saveAs } from "file-saver";
try {
this.loading = true;
// 创建一个工作簿
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 数据
this.list.forEach((t) => {
const row = [];
columns.forEach((x) => {
row.push(t[x.prop] || "");
});
// 生成的 Excel Sheet 添加数据
worksheet.addRow(row);
});
// 第一行 Header 行添加自定义样式
worksheet.getRow(1).eachCell((cell, colNumber) => {
cell.fill = {
type: "pattern",
pattern: "solid",
fgColor: {
argb: "cccccc",
},
bgColor: {
argb: "#96C8FB",
},
};
});
}
// 导出的文件名
const code = this.exportTemple.code || new Date().getTime();
workbook.xlsx.writeBuffer().then((buffer) => {
// 调用 第三方库 下载刚生成好的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;
}
S'il
大数据的量导出
est recommandé de l'implémenter sur le backend, le frontend doitwebsocket
être optimisé pour éviter une mauvaise expérience utilisateur causée par un chargement long.