Published on

Ant Design Vue 实现表单上传 Excel 文件时校验行数

Reading time
3 分钟
作者

最近在开发时遇到这样的需求:对上传的 Excel 文件行数进行校验,行数超过 1000 则提示用户数据超限。本来该校验是在用户选择文件后由前端校验,后续临时变更为上传文件后由后端校验,但是前端代码已经开发完毕了,直接删除怪可惜的,遂记录。

完整代码实现

想要在线尝试可以点击这里👉 在线代码

<template>
  <div id="app">
    <a-form :form="batchImportForm">
      <!-- 文件上传 -->
      <a-form-item label="文件上传">
        <a-upload
          v-decorator="['uploadFile', fileOption]"
          accept=".xlsx,.xls"
          :file-list="fileList"
          :remove="handleRemove"
          :before-upload="handleBeforeUpload"
        >
          <a-button shape="round">文件上传</a-button>
        </a-upload>
      </a-form-item>
    </a-form>
  </div>
</template>

<script>
import * as XLSX from "xlsx";

export default {
  name: "App",
  data() {
    return {
      // 批量导入表单
      batchImportForm: this.$form.createForm(this),
      // 文件列表
      fileList: [],
    };
  },
  computed: {
    // 文件上传表单校验
    fileOption() {
      return {
        rules: [
          {
            message: "文件条数超限,最多10条",
            validator: this.isFileEntryExceed,
          },
        ],
      };
    },
  },
  methods: {
    handleRemove() {
      this.fileList = [];
    },
    handleBeforeUpload(file) {
      this.fileList = [file];
      return false;
    },
    // 判断文件条数是否超限 10 条,表头不计
    isFileEntryExceed(rule, value, callback) {
      const reader = new FileReader();
      reader.onload = (event) => {
        const data = new Uint8Array(event.target.result);
        const workbook = XLSX.read(data, { type: "array" });
        const firstSheetName = workbook.SheetNames[0];
        const worksheet = workbook.Sheets[firstSheetName];
        const jsonData = XLSX.utils.sheet_to_json(worksheet);
        const rowCount = jsonData.length;
        if (rowCount > 10) {
          callback(new Error(rule.message));
        }
        callback();
      };
      reader.readAsArrayBuffer(value.file);
    },
  },
};
</script>

行数校验

以 Excel 文件的第一个 Sheet 页为例,使用 xlsx 库将文件转换为 JSON 数据,然后获取数据的长度即可。

// 判断文件条数是否超限 10 条,表头不计
function isFileEntryExceed(rule, value, callback) {
  const reader = new FileReader();
  reader.onload = (event) => {
    const data = new Uint8Array(event.target.result);

    const workbook = XLSX.read(data, { type: "array" });
    const firstSheetName = workbook.SheetNames[0];
    const worksheet = workbook.Sheets[firstSheetName];
    const jsonData = XLSX.utils.sheet_to_json(worksheet);

    const rowCount = jsonData.length;
    // 需要注意的是表头不计入行数
    if (rowCount > 10) {
      callback(new Error(rule.message));
    }
    callback();
  };

  reader.readAsArrayBuffer(value.file);
}