Recientemente, a menudo hago
Excel
importaciones irregulares o algunasExcel
exportaciones comunes. En la actualidad, lo mencionado anteriormente son implementaciones de front-end puras, hablemos de los esquemas de implementación de exportación e importación de Excel que se usan con frecuencia. Este artículo implementa la pila de tecnología con Vue2 +JS como ejemplo
Categorías de importación:
- Llamar
API
Los datos son completamente analizados y limpiados por el backend, y el frontend solo es responsable de llamarAPI
;- La interfaz analiza
Excel
, limpia los datos y procesa los datos correspondientes en elAPI
JSON requerido (este artículo presenta esto principalmente)
Categorías de exportación:
- La llamada
API
es generada completamente por el backendExcel
, y el frontend obtieneAPI
el nombre del archivo devuelto y lo descarga;- La interfaz se genera en función de datos JSON y luego se descarga
Excel
utilizando una biblioteca de terceros (este artículo presenta principalmente esto)file-saver
La importación Excel
necesita usar xlsx
esta biblioteca npm
Excel
Es necesario utilizar la exportación exceljs
, file-saver
estos dos
Simplemente npm instala la biblioteca correspondiente directamente;
1. Importar Excel y procesar datos
1.1 Ejemplo de requisitos
Si ahora tengo un Excel de este tipo que necesita ser importado, la interfaz es responsable de analizar el Excel y limpiar los datos, y la API solo necesita de 4 a 5 campos útiles.
1.2 Implementación específica – parte 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 Implementación específica – hoja única
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 Implementación específica: múltiples hojas
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 Parámetros relacionados
tipo de lectura de archivo
tipo | entrada esperada |
---|---|
base64 | Cadena de tipo codificada en Base64 |
binario | cadena binaria (el byte n es data.charCodeAt(n)) |
cadena | Cadena JS (solo para formato de texto UTF-8) |
buffer | El tipo de buffer de nodejs |
formación | formación |
archivo | La ruta al archivo que se leerá (solo nodejs) |
método común
sheet_to_*
La función acepta una hoja de trabajo y un objeto de opciones opcional, principalmente para convertir el archivo de Excel al formato de datos correspondiente, generalmente utilizado al importar el archivo de Excel.*_to_sheet
La función acepta un objeto de datos y un objeto de opciones opcional, principalmente para convertir el formato de datos en un archivo de Excel, que generalmente se usa al exportar archivos.sheet_add_*
La función acepta hojas de trabajo, datos y opciones opcionales. El objetivo principal es actualizar un objeto de hoja de trabajo existente.
2. Según los datos existentes, exporte Excel según sea necesario.
1.1 Ejemplo de requisitos
Si ahora tengo una tabla de consulta de este tipo que necesita exportarse, porque todos los datos están en la tabla, se
API
puede implementar sin llamar
1.2 Implementación específica
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;
}
Si
大数据的量导出
se recomienda implementarlo en el backend, el frontend debewebsocket
optimizarse para evitar una mala experiencia de usuario causada por una carga prolongada.