Vue+EasyExcel实现Excel的导入导出功能
程序员文章站
2022-04-13 15:43:05
...
需要技术EasyExcel支持:https://www.yuque.com/easyexcel/doc/easyexcel
导出Excel
效果预览
代码奉上
Vue页面
带选中框的表格是直接从element-ui官网复制过来的
选中数据->选中的数据存放在data中的json_data变量中
点击导出Excel->将data中json_data的数据处理成后端想要的格式使用JSON.stringify()转化成Json字符串发送给后端接口
带选中框的表格
<template>
<el-table
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
label="日期"
width="120">
<template slot-scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="120">
</el-table-column>
<el-table-column
prop="address"
label="地址"
show-overflow-tooltip>
</el-table-column>
</el-table>
<div style="margin-top: 20px">
<el-button @click="toggleSelection([tableData[1], tableData[2]])">切换第二、第三行的选中状态</el-button>
<el-button @click="toggleSelection()">取消选择</el-button>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [{
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-08',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-06',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-07',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}],
multipleSelection: []
}
},
methods: {
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
}
}
}
</script>
导出Excel按钮
<el-button type="primary" icon="el-icon-edit" @click="export_excel()" style="margin-top: 25px;">导出选中订单.Excel</el-button>
按钮绑定的点击事件方法
//导出选中Excel
export_excel(){
const h = this.$createElement;
if (this.json_data.length==0){
//如果没有选中任何数据
this.$notify({
type: 'error',
title: '导出失败',
message: h('i', { style: 'color: red'}, "您还没有选中任何订单数据")
});
return "sda";
}
let params=new URLSearchParams();
//处理封装orderData对象
let orderDatas=[];
for (let i = 0; i < this.json_data.length; i++) {
let order_data=this.json_data[i];
let orderData={};
let costStatus="";
switch (order_data.costStatus) {
case 0:costStatus="未支付";break;
case -1:costStatus="乘客取消";break;
case -2:costStatus="管理员取消";break;
case -3:costStatus="系统取消";break;
case -4:costStatus="失败";break;
case 1:costStatus="已支付";break;
case 2:costStatus="派车中";break;
case 3:costStatus="进行中";break;
case 4:costStatus="订单完成";break;
}
if(order_data.client==null){
orderData={origin:order_data.origin,destination:order_data.destination,beginTime:order_data.beginTime,endTime:order_data.endTime,node:"暂时没有备注",clname:"已删除",clphone:"已删除",clidCard:"已删除",sname:order_data.seller.ename,cost:order_data.cost,costStatus:costStatus};
}else {
orderData={origin:order_data.origin,destination:order_data.destination,beginTime:order_data.beginTime,endTime:order_data.endTime,node:"暂时没有备注",clname:order_data.client.clname,clphone:order_data.client.clphone,clidCard:order_data.client.clidcard,sname:order_data.seller.ename,cost:order_data.cost,costStatus:costStatus};
}
orderDatas[i]=orderData;
}
params.append("orderDatas",JSON.stringify(orderDatas));
let _this=this;
this.axios.post("/file/download",params)
.then(res=>{
this.$notify({
type: 'success',
title: '导出成功',
message: h('p', null, [
h('i', { style: 'color: red' }, 'Go+订单.xlsx'),
h('span', null, ' 成功导出到'),
h('i', { style: 'color: teal' }, res.data)
])
});
}).catch(function(error) {
_this.$notify({
type: 'error',
title: '下载失败',
message: h('i', { style: 'color: red'}, "请检查文件是不是已经存在或打开")
});
});
},
Controller层接口
将传递过来的JSON字符串转换成OrderData类型的List集合使用在Excel doWrite()导出中
需要先导入EasyExcel依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
接口
String PATH="D:\\谷歌下载\\";
/**
* 将传递过来的JSON字符串转换成OrderData类型的List集合使用在Excel doWrite()导出中
* @param orderDatas
* @return
*/
@RequestMapping("/download")
public String downloadExcel(String orderDatas) {
// 写法1
String fileName = PATH+ ExcelDateUtils.getDateString("go+订单模板") +".xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// write(fileName, 格式类)
//sheet (表名)
//doWrite(数据)
List orderList = JSON.parseArray(orderDatas,OrderData.class);
EasyExcel.write(fileName, OrderData.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("模板").doWrite(orderList);
return PATH;
}
Excel 批量导入数据
效果预览
代码奉上
Vue导入按钮
element-ui官网的按钮action绑定事件
点击按钮->选择文件->调用后台接口->调用上传成功方法->异步刷新表格https://blog.csdn.net/liudachu/article/details/109207192
<el-upload
class="upload-demo"
action="/api/file/upload"
:on-success="upload_success"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
multiple
:limit="3"
:on-exceed="handleExceed"
:file-list="fileList">
<el-button type="primary">点击导入Excel文件</el-button>
</el-upload>
按钮绑定的方法
/*Excel上传成功!*/
upload_success(file, fileList){
const h = this.$createElement;
this.$notify({
type: 'success',
title: '导入成功',
message: h('p', null, [
h('i', { style: 'color: teal' }, file),
h('span', null, ' 成功导入!'),
])
});
//异步刷新
this.reload();
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
},
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${ file.name }?`);
},
Controller接口:
1.获取传递过来的CommonsMultipartFile文件
2.保存文件到(上传路径)服务器
3.使用EasyExcel读取Excel文件,并调用Listenter进行数据库数据的导入
@Autowired
private FileMapper fileMapper;
/**
* 1.获取传递过来的CommonsMultipartFile文件
* 2.保存文件到(上传路径)服务器
* 3.使用EasyExcel读取Excel文件,并调用Listenter进行数据库数据的导入
* @param file
* @return
* @throws IOException
*/
@RequestMapping("/upload")
public String uploadExcel(@RequestParam("file") CommonsMultipartFile file) throws IOException {
//获取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
/**
* 使用springmvc中的CommonsMultipartFile进行文件的保存
*/
//上传路径保存设置
String path = "D:\\谷歌下载\\GO+订单\\";
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
// System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的方法直接写文件(注意这个时候)
file.transferTo(new File(realPath +"/"+ uploadFileName));
/**
* 使用EasyExcel读取Excel文件 进行数据的导入
*/
EasyExcel.read(path+uploadFileName, OrderData.class, new OrderDataListener(fileMapper)).sheet().doRead();
//返回文件名
return uploadFileName;
}
Listener
package com.chif.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.chif.dao.FileMapper;
import com.chif.pojo.OrderData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
// 有个很重要的点 OrderDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class OrderDataListener extends AnalysisEventListener<OrderData> {
private static final Logger LOGGER = LoggerFactory.getLogger(OrderDataListener.class);
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<OrderData> list = new ArrayList<OrderData>();
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
//private DemoDAO demoDAO;
private FileMapper fileMapper;
/* public OrderDataListener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
demoDAO = new DemoDAO();
}*/
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param fileMapper
*/
public OrderDataListener(FileMapper fileMapper) {
this.fileMapper = fileMapper;
}
/**
* 这个每一条数据解析都会来调用
*
* @param data
* one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(OrderData data, AnalysisContext context) {
//System.out.println(JSON.toJSONString(data));
data.setCreateTime(new Date());
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
*
* DemoData 类型
* AnalysisContext 分析上下文
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
fileMapper.addOrdersByList(list);
LOGGER.info("存储数据库成功!");
}
}
调用的持久层mapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chif.dao.FileMapper">
<insert id="addOrdersByList" parameterType="java.util.List">
insert into db_go.t_order
(origin, destination, begin_time, end_time, node, client_id, bus_id, seller_id, cost, cost_status, create_time)
values
<foreach collection="list" item="item" index="index" separator="," >
(#{item.origin},#{item.destination},#{item.beginTime},#{item.endTime},#{item.node},
(select cl_id from db_go.t_client where cl_name=#{item.clname}),
1,
(select e_id from db_go.t_emp where e_name=#{item.sname}),
#{item.cost},
(select id from t_status where status=#{item.costStatus}),
#{item.createTime})
</foreach>
</insert>
</mapper>
EasyExcel需要封装的实体类
package com.chif.pojo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.util.Date;
@Data
@HeadRowHeight(20)
// 头字体设置成20
@HeadFontStyle(fontHeightInPoints = 10)
public class OrderData {
@ExcelProperty("出发地点")
private String origin;//出发地点
@ExcelProperty("目的地")
private String destination;//目的地
@ExcelProperty("出发时间")
private Date beginTime;//出发时间
@ExcelProperty("预计结束时间")
private Date endTime;//预计结束时间
@ExcelProperty("备注")
private String node;//备注
@ExcelProperty("乘客姓名")
private String clname;//乘客姓名
@ExcelProperty("乘客电话")
private String clphone;//乘客电话
@ExcelProperty("乘客身份证号")
private String clidCard;//乘客身份证号
@ExcelProperty("售票员姓名")
private String sname;//售票员姓名
@ExcelProperty("费用")
private String cost;//费用
@ExcelProperty("缴费状态")
private String costStatus;
@ExcelIgnore
private Date createTime;
}
完结
上一篇: 折线分割平面
下一篇: 4. Spark实战项目——电商指标统计
推荐阅读
-
vue实现word,pdf文件的导出功能
-
用Excel数据验证功能实现单元格只能输入正值就是大于0的正数
-
Excel-Boot(一款Excel导入导出解决方案组成的轻量级开源组件)
-
【C#常用方法】2.DataTable(或DataSet)与Excel文件之间的导出与导入(使用NPOI)
-
PHP+MySQL实现海量数据导入导出的总结:is_numbric函数的坑
-
利用phpexcel把excel导入数据库和数据库导出excel实现
-
Python实现的在特定目录下导入模块功能分析
-
java实现CSV文件导入与导出功能
-
vue中导出Excel表格的实现代码
-
ASP将Excel数据导入到SQLServer的实现代码