# 前言

# ✨魁首

🔔一个没有天赋的前端程序员👨‍💻 💡博客

# 🔰关注我

🤖Github |🔑CSDN | 💎掘金 | 📖 知乎 | 💡博客 |

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

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

# 准备前的工作

1、安装 xlsx

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

2、局部引入 xlsx

import XLSX from "xlsx";
1

# 导入具体实现

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>
1
2
3

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);
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

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>  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40