Vue+EasyExcel实现Excel的导入导出功能

it2025-01-14  5

需要技术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; }

完结

最新回复(0)