Implémentation frontale pure de l'importation et de l'exportation d'Excel

Récemment, je fais souvent Exceldes importations irrégulières, ou certaines Excelexportations 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 :

  1. Appel APILes données sont entièrement analysées et nettoyées par le backend, et le frontend n'est responsable que de l'appel API;
  2. Le frontal analyse Excel, nettoie les données et traite les données correspondantes dans le APIJSON requis ; (cet article présente principalement ceci)

Catégories d'exportation :

  1. L'appel APIest entièrement généré par le backend Excel, et le frontend obtient APIle nom du fichier renvoyé et le télécharge ;
  2. 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 Exceldoit utiliser xlsxcette bibliothèque npm

L'exportation Exceldoit être utilisée exceljs, file-saverces deux-là

Npm installe simplement la bibliothèque correspondante directement ;

1. Importez Excel et traitez les données

1.1 Exemple d'exigence

insérer la description de l'image ici

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_sheetLa 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

insérer la description de l'image ici

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 APIpeut ê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 doit websocketêtre optimisé pour éviter une mauvaise expérience utilisateur causée par un chargement long.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_56650035/article/details/132666602
conseillé
Classement