• Vue中使用el-upload+XLSX实现解析excel文件为json数据


    场景

    业务要求为实现每天上报各部门计划人数,需要通过excel导入数据。

    前端可以解析excel数据并进行初步的格式校验。

    导入成功之后解析的数据

    excel里的数据为

    注:

    博客:
    https://blog.csdn.net/badao_liumang_qizhi 
    关注公众号
    霸道的程序猿
    获取编程相关电子书、教程推送与免费下载。

    实现

    npm安装以及注意事项

    npm i xlsx@0.16.8

    这里是指定版本安装的,一开始未指定版本,安装之后提示如下两个问题

    Failed to execute 'readAsBinaryString' on 'FileReader': parameter 1 is not of type 'Blob'

     Cannot read property 'read' of undefined
        at FileReader.reader

    代码实现流程

    首先在页面中引入

    import XLSX from "xlsx";

    然后页面添加el-upload

    1.     <el-upload
    2.       ref="upload"
    3.       :limit="1"
    4.       accept=".xlsx, .xls"
    5.       :headers="headers"
    6.       :action="upLoadUrl + '?planDateString=' + this.planDate"
    7.       :disabled="isUploading"
    8.       :on-progress="handleFileUploadProgress"
    9.       :on-success="handleFileSuccess"
    10.       :auto-upload="false"
    11.       :before-upload="beforeUpload"
    12.       drag
    13.     >
    14.       <i class="el-icon-upload"></i>
    15.       <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
    16.       <div class="el-upload__tip text-center" slot="tip">
    17.         <span>仅允许导入xls、xlsx格式文件。</span>
    18.       </div>
    19.     </el-upload>

    设置其before-upload属性,上传文件之前的钩子,参数为上传的文件,若返回false或者

    返回Promise且被reject则停止上传。

    实现其bofore-upload

    1.     //上传文件之前的钩子
    2.     beforeUpload(file) {
    3.       //解析excel
    4.       this.analysisExcel(file).then((tableJson) => {
    5.         if (tableJson && tableJson.length > 0) {
    6.           //成功解析出数据
    7.           //只取第一个sheet的数据
    8.           let dataExcel = tableJson[0];
    9.           console.log("数据", dataExcel);
    10.           console.log(JSON.stringify(dataExcel.sheet));
    11.         }
    12.       });
    13.     },
    14.     //解析excel
    15.     analysisExcel(file) {
    16.       return new Promise(function (resolve, reject) {
    17.         const reader = new FileReader();
    18.         reader.onload = function (e) {
    19.           const data = e.target.result;
    20.           let datajson = XLSX.read(data, {
    21.             type: "binary",
    22.           });
    23.           const result = [];
    24.           datajson.SheetNames.forEach((sheetName) => {
    25.             result.push({
    26.               sheetName: sheetName,
    27.               sheet: XLSX.utils.sheet_to_json(datajson.Sheets[sheetName]),
    28.             });
    29.           });
    30.           resolve(result);
    31.         };
    32.         reader.readAsBinaryString(file);
    33.       });
    34.     },

    完整示例代码

    1. <template>
    2.   <!-- 用户导入对话框 -->
    3.   <el-dialog :title="title" :visible.sync="open" width="400px" append-to-body>
    4.     <div class="block">
    5.       <span class="demonstration">计划日期: </span>
    6.       <el-date-picker
    7.         v-model="planDate"
    8.         type="date"
    9.         placeholder="选择计划日期"
    10.         size="small"
    11.         value-format="yyyy-MM-dd"
    12.       >
    13.       </el-date-picker>
    14.     </div>
    15.     <br />
    16.     <el-upload
    17.       ref="upload"
    18.       :limit="1"
    19.       accept=".xlsx, .xls"
    20.       :headers="headers"
    21.       :action="upLoadUrl + '?planDateString=' + this.planDate"
    22.       :disabled="isUploading"
    23.       :on-progress="handleFileUploadProgress"
    24.       :on-success="handleFileSuccess"
    25.       :auto-upload="false"
    26.       :before-upload="beforeUpload"
    27.       drag
    28.     >
    29.       <i class="el-icon-upload"></i>
    30.       <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
    31.       <div class="el-upload__tip text-center" slot="tip">
    32.         <span>仅允许导入xls、xlsx格式文件。</span>
    33.       </div>
    34.     </el-upload>
    35.     <div slot="footer" class="dialog-footer">
    36.       <el-button type="primary" @click="submitFileForm">确 定</el-button>
    37.       <el-button @click="open = false">取 消</el-button>
    38.     </div>
    39.   </el-dialog>
    40. </template>
    41. <script>
    42. import { getToken } from "@/utils/auth";
    43. import XLSX from "xlsx";
    44. import moment from "moment";
    45. export default {
    46.   data() {
    47.     return {
    48.       // 是否显示弹出层(用户导入)
    49.       open: false,
    50.       // 弹出层标题(用户导入)
    51.       title: "",
    52.       // 是否禁用上传
    53.       isUploading: false,
    54.       //计划日期
    55.       planDate: new Date(),
    56.       // 设置上传的请求头部
    57.       headers: { Authorization: "Bearer " + getToken() },
    58.       // 上传的地址
    59.       upLoadUrl: "",
    60.     };
    61.   },
    62.   mounted() {
    63.     //默认计划日期为明天
    64.     this.planDate = moment().subtract(-1, "days").format("YYYY-MM-DD");
    65.   },
    66.   methods: {
    67.     /** 导入按钮操作 */
    68.     handleImport(data) {
    69.       this.title = data.title;
    70.       this.upLoadUrl = process.env.VUE_APP_BASE_API + data.upLoadUrl;
    71.       this.open = true;
    72.     },
    73.     // 提交上传文件
    74.     submitFileForm() {
    75.       this.$refs.upload.submit();
    76.     },
    77.     // 文件上传中处理
    78.     handleFileUploadProgress() {
    79.       this.isUploading = true;
    80.     },
    81.     // 文件上传成功处理
    82.     handleFileSuccess(response) {
    83.       this.open = false;
    84.       this.isUploading = false;
    85.       this.$refs.upload.clearFiles();
    86.       this.$alert(
    87.         "
      " +
    88.           response.msg +
    89.           "
      ",
  •         "导入结果",
  •         { dangerouslyUseHTMLString: true }
  •       );
  •       //上传数据成功后重新请求数据
  •       this.$emit("getList");
  •     },
  •     //上传文件之前的钩子
  •     beforeUpload(file) {
  •       //解析excel
  •       this.analysisExcel(file).then((tableJson) => {
  •         if (tableJson && tableJson.length > 0) {
  •           //成功解析出数据
  •           //只取第一个sheet的数据
  •           let dataExcel = tableJson[0];
  •           console.log("数据", dataExcel);
  •           console.log(JSON.stringify(dataExcel.sheet));
  •         }
  •       });
  •     },
  •     //解析excel
  •     analysisExcel(file) {
  •       return new Promise(function (resolve, reject) {
  •         const reader = new FileReader();
  •         reader.onload = function (e) {
  •           const data = e.target.result;
  •           let datajson = XLSX.read(data, {
  •             type: "binary",
  •           });
  •           const result = [];
  •           datajson.SheetNames.forEach((sheetName) => {
  •             result.push({
  •               sheetName: sheetName,
  •               sheet: XLSX.utils.sheet_to_json(datajson.Sheets[sheetName]),
  •             });
  •           });
  •           resolve(result);
  •         };
  •         reader.readAsBinaryString(file);
  •       });
  •     },
  •   },
  • };
  • </script>
  • <style>
  • </style>
  • 相关阅读:
    入手评测R7 6800u和i7 1165g7差距 r76800u和i71165g7对比
    所有子数组的(最小值 x 累加和)中的最大值
    FTP文件共享服务
    《许犁庭与柔性世界》第十六章 五大势力
    HDL-Bits 刷题记录 01
    什么是Air-gapped test or development environments?
    k8s-service-3-clusterip
    Flutter 开发者工具 Android Studio 开发Flutter应用
    fastjson 序列化 输出空字段
    http内网穿透CYarp[开源]
  • 原文地址:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127830581