一、前言
项目中遇到将table表格导出为excel和导入excel表格数据到table表格中的功能,自此记录下来。
二、依赖安装
分别安装js-table2excel和xlsx
npm install js-table2excel
npm install xlsx
这里我也用到了
示例文件
完整代码
注释都在代码中了
<template>
<div>
<div style="display: flex; align-items: center;margin-bottom: 10px;">
<el-upload action="#" :show-file-list="false" :before-upload="importBefore" accept=".xls,.xlsx"
style="margin: 0 12px;display: flex;align-items: center;">
<el-button type="success">表格导入</el-button>
</el-upload>
<el-button type="success" @click="userExport">导出表格</el-button>
</div>
<el-table :data="tableData" border style="width: 100%" ref="tableRef">
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="date" label="日期" width="180" />
<el-table-column prop="name" label="名称" width="180" />
<el-table-column prop="address" label="地址" />
<el-table-column prop="age" label="性别">
<template slot-scope="scope" #default="scope">
{{ fieldChange(scope.row['age']) }}
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { ElMessage, ElMessageBox, ElButton, ElLoading } from 'element-plus'
import { reactive, toRefs, ref, onMounted, h } from 'vue'
import table2Excel from 'js-table2excel'
import * as XLSX from "xlsx"
const state = reactive({
tableData: [
{
date: '2022/11/12 10:16:56',
name: 'Tom',
address: 'No. 1, Grove St, Los Angeles',
age: 1
},
{
date: '2022/11/12 10:16:56',
name: 'Tom',
address: 'No. 1, Grove St, Los Angeles',
age: 1
},
{
date: '2022/11/12 10:16:56',
name: 'Tom',
address: 'No. 1, Grove St, Los Angeles',
age: 2
},
{
date: '2022/11/12 10:16:56',
name: 'Tom',
address: 'No. 1, Grove St, Los Angeles',
age: 2
},
],
exportConfig: [
{
title: '时间',
key: 'date',
type: 'text'
},
{
title: '姓名',
key: 'name',
type: 'text'
},
{
title: '地址',
key: 'address',
type: 'text'
},
{
title: '性别',
key: 'age',
type: 'text'
},
],
formatColumns: [
{
prop: 'age',
option: {
'1': '男',
'2': '女'
},
},
]
})
const { tableData, exportConfig, formatColumns } = toRefs(state)
const tableRef = ref()
const userExport = () => {
ElMessageBox({
title: '导出Excel表格',
draggable: true,
showCancelButton: true,
showConfirmButton: false,
message: h('div', null, [
h(ElButton, { text: true, type: 'primary', innerHTML: '导出选中数据', onClick: assignExport }),
h(ElButton, { text: true, type: 'success', innerHTML: '导出所有数据', onClick: allExport })
])
}).then((res) => { }).catch((res) => { })
}
function assignExport() {
let arr = tableRef.value.getSelectionRows()
if (!arr.length) {
return ElMessage({
message: '请选择需要导出的数据',
type: 'warning',
})
}
ElMessageBox.close()
const loading = ElLoading.service({
lock: true,
text: '请稍等...',
background: 'rgba(255, 255, 255, 0.5)',
})
let list = JSON.stringify(tableRef.value.getSelectionRows())
list = formatExportData(JSON.parse(list))
console.log(list)
table2Excel(state.exportConfig, list, '导出数据')
loading.close()
}
async function allExport() {
ElMessageBox.close()
const loading = ElLoading.service({
lock: true,
text: '请稍等...',
background: 'rgba(255, 255, 255, 0.5)',
})
let list = JSON.stringify(state.tableData)
list = formatExportData(JSON.parse(list))
table2Excel(state.exportConfig, list, '导出数据')
loading.close()
}
function formatExportData(list) {
list.forEach((item) => {
state.formatColumns.forEach((i) => {
item[i.prop] = i.option[item[i.prop]]
})
for (let key in item) {
if (!item[key] && item[key] == null) {
item[key] = ""
}
}
});
return list
}
function importBefore(file) {
const reader = new FileReader();
reader.onload = (e) => {
const data = e.target.result;
const workbook = XLSX.read(data, { type: "array" });
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const results = XLSX.utils.sheet_to_json(worksheet);
importAdd(results)
};
reader.readAsArrayBuffer(file);
}
function importAdd(list) {
list.forEach((item) => {
state.exportConfig.forEach((i) => {
item[i.key] = item[i.title]
delete item[i.title]
})
for (let key in item) {
if (key == "date") {
item[key] = ExcelDateToJSDate(item[key])
}
}
})
list = convertImportData(list)
console.log(list)
}
function ExcelDateToJSDate(serial) {
var utc_days = Math.floor(serial - 25569);
var utc_value = utc_days * 800;
var date_info = new Date(utc_value * 1000);
var fractional_day = serial - Math.floor(serial) + 0.0000001;
var total_seconds = Math.floor(800 * fractional_day);
var seconds = total_seconds % 60;
total_seconds -= seconds;
var hours = Math.floor(total_seconds / (60 * 60));
var minutes = Math.floor(total_seconds / 60) % 60;
return new Date(date_info.getFullYear(), date_info.getMonth(), date_info.getDate(), hours, minutes, seconds);
}
function convertImportData(list) {
list.forEach((item) => {
state.formatColumns.forEach((i) => {
for (let key in i.option) {
if (item[i.prop] == i.option[key]) {
item[i.prop] = key
}
}
})
for (let key in item) {
if (!item[key] && item[key] == undefined) {
item[key] = ""
}
}
});
return list
}
function fieldChange(row, option = { '1': '男', '2': '女' }) {
if (option[row]) {
return option[row]
}
}
</script>
<style scoped></style>
弊端
没有实现Excel表格中的图片导入
在导出为Excle表格时,时间是没问题的。
导入时,时间会存在秒数上的误差。
有大佬知道原因或者解决办法,可以评论留言。