【vue Excelインポート・エクスポート】Vueは複雑なヘッダーExcelテーブルをエクスポート・インポートする機能をシンプルに実装【純粋なフロントエンド版とバックエンド版】

はじめに
これは Excel テーブルのインポートとエクスポートによく使用される機能ですが、私の場合は 3 層のヘッダー テーブルなど、
複雑なヘッダーを含むテーブルのエクスポートとインポートが頻繁に行われます。ネットで調べた結果、非常に簡単なエクスポートとインポートの方法を見つけました。もちろん、これは純粋なフロントエンド バージョンであり、ページングをダウンロードするのが簡単ではない場合もあります。したがって、実際の作業では、エクスポートは引き続きバックエンドの責任となります。


エフェクト画像
は、表のスタイルです。3 層のヘッダーです。
ここに画像の説明を挿入

 「エクスポート」をクリックした後の効果と表の形式は次のとおりです。

ここに画像の説明を挿入

ここに画像の説明を挿入 

[インポート]をクリックした後の効果と取得されたデータ形式は次のとおりです。

ここに画像の説明を挿入

ここに画像の説明を挿入

 使い方の紹介

1. プラグインをダウンロードするには、次のコマンドを入力します: npm install -S  file-saver  xlsx

2. これをページに導入します。インポートとエクスポートを記述する必要があるテーブル ページに直接記述するだけです。

ここに画像の説明を挿入

3. この ID をフォームにバインドします。エクスポート時にデータを取得するために使用されます

ここに画像の説明を挿入 

ここで、データを取得してインポート後にバックエンドに渡したい場合は、ループしてこの位置で新しい配列にプッシュし、その配列をループの外のバックエンドに渡します。

ここに画像の説明を挿入 コード部分 (純粋なフロントエンドのインポートおよびエクスポート)

<template>
  <div>
    <div class="titleBtn">
      <!-- 导出Excel -->
      <el-button
        @click="exportClick"
        type="primary"
        size="small"
        style="margin: 0 20px"
        icon="el-icon-folder-opened"
        >导出</el-button
      >
      <!-- 导入Excel -->
      <el-upload
        action="/上传文件的接口"
        :on-change="onChange"
        :auto-upload="false"
        :show-file-list="false"
        accept=".xls, .xlsx"
        ref="upload"
        :multiple="true"
      >
        <el-button type="warning" icon="el-icon-folder-add" size="small"
          >导入</el-button
        >
      </el-upload>
    </div>
    <el-table :data="tableData" style="width: 100%" id="mainTable">
      <el-table-column prop="date" label="日期" width="150"> </el-table-column>
      <el-table-column label="配送信息">
        <el-table-column prop="name" label="姓名" width="120">
        </el-table-column>
        <el-table-column label="地址">
          <el-table-column prop="province" label="省份" width="120">
          </el-table-column>
          <el-table-column prop="city" label="市区" width="120">
          </el-table-column>
          <el-table-column prop="address" label="地址" width="300">
          </el-table-column>
          <el-table-column prop="zip" label="邮编" width="120">
          </el-table-column>
        </el-table-column>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import FileSaver from "file-saver";
import * as XLSX from "xlsx";
export default {
  data() {
    return {
      tableData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          province: "上海",
          city: "普陀区",
          address: "上海市普陀区金沙江路 1518 弄",
          zip: 200333,
        },
      ],
    };
  },
  methods: {
    //导出
    exportClick() {
      //第一个参数是到处后文件名,第二个是id绑定表格dom
      this.exportExcel("test", "mainTable");
    },
    //转换数据
    exportExcel(filename, tableId) {
      var xlsxParam = { raw: true }; // 导出的内容只做解析,不进行格式转换
      var table = document.querySelector("#" + tableId).cloneNode(true);
      var wb = XLSX.utils.table_to_book(table, xlsxParam);
      /* 获取二进制字符进行输出 */
      var wbout = XLSX.write(wb, {
        bookType: "xlsx",
        bookSST: true,
        type: "array",
      });
      try {
        FileSaver.saveAs(
          new Blob([wbout], { type: "application/octet-stream" }),
          filename + ".xlsx"
        );
      } catch (e) {
        if (typeof console !== "undefined") {
          console.log(e, wbout);
        }
      }
      return wbout;
    },
    //导入
    onChange(file, fileList) {
      this.readExcel(file); // 调用读取数据的方法
    },
    // 读取数据
    readExcel(file) {
      let that = this;
      if (!file) {
        //如果没有文件
        return false;
      } else if (!/.(xls|xlsx)$/.test(file.name.toLowerCase())) {
        this.$message.error("上传格式不正确,请上传xls或者xlsx格式");
        return false;
      }
      const fileReader = new FileReader();
      fileReader.onload = (ev) => {
        try {
          const data = ev.target.result;
          const workbook = XLSX.read(data, {
            type: "binary",
          });
          if (workbook.SheetNames.length >= 1) {
            this.$message({
              message: "导入数据表格成功",
              showClose: true,
              type: "success",
            });
          }
          const wsname = workbook.SheetNames[0]; //取第一张表
          const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格内容
          console.log("生成json:", ws);
          // that.tableData = [];
          for (var i = 2; i < ws.length; i++) {
            let sheetData = {
              // 键名为绑定 el 表格的关键字,值则是 ws[i][对应表头名]
              date: ws[i]["日期"],
              name: ws[i]["配送信息"],
              province: ws[i]["__EMPTY"],
              city: ws[i]["__EMPTY_1"],
              address: ws[i]["__EMPTY_2"],
              zip: ws[i]["__EMPTY_3"],
            };
            console.log("上传的数据:", sheetData);
            //添加到表格中
            that.tableData.push(sheetData);
            //正常导入需要拿到上传的数据就在这从新弄个数组push进去,然后传给后台,后台保存后查询表格返给前端。
          }
          this.$refs.upload.value = "";
        } catch (e) {
          console.log(e);
          return false;
        }
      };
      // 如果为原生 input 则应是 files[0]
      fileReader.readAsBinaryString(file.raw);
    },
  },
};
</script>
<style scoped>
.titleBtn {
  display: flex;
  margin: 20px 0;
}
</style>

 バックエンドを使用した 2 つの方法

 上記の純粋なフロントエンドの書き込み方法には問題があるため、ページングがある場合はデータを取得できません。
または、データが大きすぎるため、ダウンロードが非常に遅くなり、停止します。したがって、基本的に作業内容はすべてバックエンドによってエクスポートされ、ダウンロード リンクが生成されます。
さらに 2 つの方法を紹介します。

1、ラベルダウンロード

この方法の核心は、バックエンドがダウンロード リンクを直接生成し、フロントエンドが必要とするのは A タグを生成してダウンロードすることだけであるということです。最も一般的に使用されるものの 1 つ

daochu(){
      // A标签导出方法:通过生成一个A标签然后触发后台传过来的下载链接完成导出
      //核心注意需要给请求的格式改为:responseType: "blob",
      this.axios
          .post(
            url, {}, {
              token: true,
              responseType: "blob",
            }
          )
          .then((res) => {
            if (res.status == 200) {
              //拿到后台发过来的下载链接
              let url = window.URL.createObjectURL(new Blob([res.data]));
              //生成一个A标签
              let link = document.createElement("a");
              //样式设为none,没有大小,不占位置
              link.style.display = "none";
              //把链接地址给href
              link.href = url;
              //下载后的名字,用时间来标注避免重复
              let filename = new Date().getTime() + ".xlsx";
              //给A标签添加属性download,值为上面的名字
              link.setAttribute("download", filename);
              //在页面的尾部插入元素A标签
              document.body.appendChild(link);
              //点击A标签,这样就触发下载了。
              link.click();
            } else if (res.data.code != 200) {
              this.$message("暂无数据");
            }
            this.exporloading = false;
          })
          .catch((err) => {
            this.exporloading = false;
          });
    }

2. 上記のフロントエンド方法を使用して、ページングを行わずにバックエンドに完全な形式のデータを直接渡します。

次に、このデータを使用してテーブルの配列に値を割り当て、テーブル dom をエクスポート メソッドに渡してダウンロードします。
バックエンドがすべてのデータを提供せず、データがそれほど多くないため、すべてのデータを取得するという目的を達成するために、フロントデスクを循環して各ページのデータを配列にマージするだけです。しかし、これはお勧めできません。

ここで this.$excels はこのメソッドをカプセル化し、main.js にプロトタイプを割り当てたものです。方法は上記と同じです。

ここに画像の説明を挿入

パッケージの外観は基本的に上記と同様です。
ここに画像の説明を挿入

これはループで取得されたページ データです。85 項目すべてが取得され、tableData2 配列にコピーされ、テーブルの dom が取得され、すべてのデータのテーブルをエクスポートできます。

ここに画像の説明を挿入

テーブル内の複数シートを一度に読み出して書き込む


場合によっては、最初のシート以上のものが必要になることがあります。テーブル内に多数のシートがあり、各シートのフィールドが異なる場合があります。したがって、上記のメソッドに少し変更を加えて、次のように書くことができます。
readExcel メソッドを変更するだけです。修正内容は主に各シートのデータを読み込むループの追加です。

// 读取数据
    readExcel(file) {
      let that = this;
      if (!file) {
        //如果没有文件
        return false;
      } else if (!/.(xls|xlsx)$/.test(file.name.toLowerCase())) {
        this.$message.error("上传格式不正确,请上传xls或者xlsx格式");
        return false;
      }
      const fileReader = new FileReader();
      fileReader.onload = (ev) => {
        try {
          const data = ev.target.result;
          const workbook = XLSX.read(data, {
            type: "binary",
          });
          if (workbook.SheetNames.length >= 1) {
            //读取到表中sheet
            this.$message({
              message: "导入数据表格成功",
              showClose: true,
              type: "success",
            });
          }
          for (var i = 0; i < workbook.SheetNames.length; i++) {
            const wsname = workbook.SheetNames[i]; //取第一张表
            const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格内容
            console.log("生成json:", ws);

            // that.tableData = [];
            // for (var i = 2; i < ws.length; i++) {
            //   let sheetData = {
            //     // 键名为绑定 el 表格的关键字,值则是 ws[i][对应表头名]
            //     date: ws[i]["日期"],
            //     name: ws[i]["配送信息"],
            //     province: ws[i]["__EMPTY"],
            //     city: ws[i]["__EMPTY_1"],
            //     address: ws[i]["__EMPTY_2"],
            //     zip: ws[i]["__EMPTY_3"],
            //   };
            //   console.log("上传的数据:", sheetData);
            //   //添加到表格中
            //   that.tableData.push(sheetData);
            //   //正常导入需要拿到上传的数据就在这从新弄个数组push进去,然后传给后台,后台保存后查询表格返给前端。
            // }
          }
          this.$refs.upload.value = "";//清空上传列表,不能放在循环内清空,否则第一次循环sheet1时直接清空了上传列表,第二次循环sheet2就没数据了
        } catch (e) {
          console.log(e);
          return false;
        }
      };
      // 如果为原生 input 则应是 files[0]
      fileReader.readAsBinaryString(file.raw);
    },

複数シートの読み取りレンダリング

ここに画像の説明を挿入

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_41542329/article/details/131284287