Vue+Ant design 项目怎么导入 Excel 表格数据?

在大型项目中,对于数据量大的表格,纯粹依赖于逐个添加是不现实的,于是就有了 Excel 批量导入和导出,下面来讲解一下具体怎么实现; 准备前的工作 1、安装 xlsx /package.json "vue" : "^2.6.11" , "a...

这篇文章已从掘金同步到个人博客,原始发布地址为 掘金原文

在大型项目中,对于数据量大的表格,纯粹依赖于逐个添加是不现实的,于是就有了 Excel 批量导入和导出,下面来讲解一下具体怎么实现;

准备前的工作

1、安装 xlsx

/package.json
"vue": "^2.6.11",
"ant-design-vue": "1.7.2",
"xlsx": "^0.17.5"

2、局部引入 xlsx

import XLSX from "xlsx";

导入具体实现

1、触发事件

<a-upload name="file" :show-upload-list="false" :customRequest="doUpload" @change="changeUploadFile" >
    <a-button type="primary" style="width: 115px;"> Excel导入</a-button>
</a-upload>

2、解析本地上传的文件

changeUploadFile(e){
    let fileList = [...e.fileList];
    // 无论重复上传几次,只取最后一次上传的文件
    this.file = fileList[fileList.length - 1];
    let file = fileList[fileList.length - 1].originFileObj
    this.loadFlag = false
    let that = this;
    // 创建一个 FileReader 实例
    let fileReader = new FileReader();
    let data = [];
    let workbook;
    fileReader.onload = (ev)=>{
        try {
            data = ev.target.result;
            workbook = XLSX.read(data, {
                type: "binary"
            }); // 以二进制流方式读取得到整份excel表格对象
            data = []; // 存储获取到的数据
        } catch (e) {
            return;

        // 遍历每张表读取
        for (let sheetKey in workbook.Sheets) {
            if (workbook.Sheets[sheetKey]) {
                data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheetKey]));
                break;
            }
        }
        // 这里的键要与表格中的标题对应,否者解析不出来
        let attrMap={
            "编号": "code",
            "名称": "name",
            "备注": "description"
        };
        let createTime = Date.SERVER_TIME.getTime();
        let list = data.map((item)=>{
            let tmp = {
                createTime
            };
            for(let key in item){
                tmp[attrMap[key]] = item[key];
            }
            return tmp;
        });
                // 解析完后放到data中的list中
        that.list = list;
        that.loadFlag = true;
    };
    // 以二进制方式打开文件
    fileReader.readAsBinaryString(file);
},

3、将list渲染到表格

<a-table v-else :columns="columns" :rowClassName="()=>{return '_formRow'}" :row-selection="rowSelection" :row-key="(item,index) => {return `${index}_${item.code}`;}" :scroll="{ x:1200, y: 560 }":data-source="list" :pagination="!1">
        <!-- 编号 -->
    <template slot="code" slot-scope="text, record">
        <a-input v-if="record.editable" size="small" style="margin: -5px 0" v-model.trim="record.code"
            @change="e => handleChange(e.target.value, record, key='code')"
            @blur="inputLimit(record.code, record, key='code')"/>
        <div v-else>
            <span class="overflowText">{{ record.code }}</span>
            <a-tooltip v-if="contentDataCheck(record)" tigger="hover" title="当前行存在错误信息,请检查。" placement="top">
                <icon type="icon-warn" class="infoIcon" style="line-height: 20px; margin-left: 4px; color: #FAAD14; font-size: 15px;"></icon>
            </a-tooltip>
        </div>
    </template>
    <!-- 名称 -->
    <template slot="name" slot-scope="text, record">
        <a-input v-if="record.editable" size="small" style="margin: -5px 0" v-model.trim="record.name"/>
        <a-tooltip v-else tigger="hover" :title="record.name" placement="topLeft">
            <div class="overflowText">{{ record.name }}</div>
        </a-tooltip>
    </template>
    <!-- 备注 -->
    <template slot="description" slot-scope="text, record">
        <a-input v-if="record.editable" size="small" style="margin: -5px 0" v-model.trim="record.description"/>
        <a-tooltip v-else tigger="hover" placement="left">
            <div slot="title" style="max-width: 250px;word-break: break-all">{{ record.description }}</div>
            {{record.description !== undefined ? record.description : '-'}}
        </a-tooltip>
    </template>
    <template slot="option" slot-scope="text, record, index">
        <div class="editable-row-operations">
            <span v-if="record.editable" style="display: inline-flex;">
                <a-button type="primary" size="small" @click="() => save(record)" style="margin-right: 8px;">保存</a-button>
                <a-button size="small" @click="() => cancel(record)">取消</a-button>
            </span>
            <span v-else>
                <a :disabled="editingKey !== ''" @click="() => edit(index, record)">编辑</a>
            </span>
        </div>
    </template>
</a-table>