Implementação front-end pura de importação e exportação de Excel

Recentemente, costumo fazer Excelimportações irregulares ou algumas Excelexportações comuns. No momento, os mencionados acima são implementações de front-end puras; vamos falar sobre os esquemas de implementação de exportação e importação do Excel que são frequentemente usados. Este artigo implementa a pilha de tecnologia com Vue2 + JS como exemplo

Categorias de importação:

  1. Chamando APIOs dados são completamente analisados ​​e limpos pelo backend, e o frontend é responsável apenas por chamar API;
  2. O front-end analisa Excel, limpa os dados e processa os dados correspondentes no APIJSON necessário; (este artigo apresenta isso principalmente)

Categorias de exportação:

  1. A chamada APIé totalmente gerada pelo backend Excele o frontend obtém APIo nome do arquivo retornado e faz o download;
  2. O front-end é gerado com base em dados JSON e depois baixado Excelusando uma biblioteca de terceiros ; (este artigo apresenta isso principalmente)file-saver

A importação Excelprecisa usar xlsxesta biblioteca npm

A exportação Excelprecisa ser usada exceljs, file-saveresses dois

Basta npm instalar a biblioteca correspondente diretamente;

1. Importe Excel e processe dados

1.1 Exemplo de requisitos

insira a descrição da imagem aqui

Se agora eu tiver um Excel desse tipo que precisa ser importado, o front end será responsável por analisar o Excel e limpar os dados, e a API precisará apenas de 4 a 5 campos úteis

1.2 Implementação 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 Implementação específica – folha ú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 Implementação específica – múltiplas planilhas

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 leitura de arquivo

tipo entrada esperada
base64 String de tipo codificado em Base64
binário string binária (byte n é data.charCodeAt(n))
corda String JS (somente para formato de texto UTF-8)
amortecedor O tipo de buffer do nodejs
variedade variedade
arquivo O caminho para o arquivo que será lido (somente nodejs)

método comum

  • sheet_to_*A função aceita uma planilha e um objeto de opções opcionais, principalmente para converter o arquivo excel no formato de dados correspondente, geralmente usado na importação do arquivo excel
  • *_to_sheetA função aceita um objeto de dados e um objeto de opções opcionais, principalmente para converter o formato dos dados em um arquivo Excel, que geralmente é usado na exportação de arquivos
  • sheet_add_*A função aceita planilha, dados e opções opcionais. O objetivo principal é atualizar um objeto de planilha existente

2. De acordo com os dados existentes, exporte o Excel conforme necessário

1.1 Exemplo de requisitos

insira a descrição da imagem aqui

Se eu tiver agora uma tabela de consulta desse tipo que precisa ser exportada, porque todos os dados estão na tabela, ela APIpode ser implementada sem chamar

1.2 Implementação 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;
}

Se 大数据的量导出for recomendado implementá-lo no backend, o frontend deve websocketser otimizado para evitar uma experiência ruim do usuário causada por carregamento demorado

Acho que você gosta

Origin blog.csdn.net/weixin_56650035/article/details/132666602
Recomendado
Clasificación