SpringBoot整合easyexcel实现Excel的导入与导出
导出
在一般不管大的或者小的系统中,各家的产品都一样,闲的无聊的时候都喜欢让我们这些程序员导出一些数据出来供他观赏,非说这是必须需求,非做不可,那么我们就只能苦逼的哼哧哼哧的写bug喽。
之前使用POI导出excel需要自己先去创建excel文件,还要创建sheet,写表头,操作起来确实很麻烦,针对产品这种随心而欲的需求我们能不能快速的做完这样一个产品看起来挺简单的功能。
基于这样一个快速开发的场景,我们来看看easyexcel应该如何使用。
首先我们创建一个springboot(版本是 2.1.4.RELEASE)项目,在此就不过多的啰嗦,创建好之后,首先需要引入easyexcel的maven坐标。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>1.1.2-beta5</version>
</dependency>
导入好了之后,我们接下来需要创建一个导出的模板类,首先要集成BaseRowModel,set、get省略,@ExcelProperty注解中的value就是表头的信息,index是在第几列,没有加注解的不会导出。
public class OrderExcelBO extends BaseRowModel {
@ExcelProperty(value = {"订单ID"}, index = 0)
private String id;
/**
* 订单描述
*/
@ExcelProperty(value = {"订单描述"}, index = 2)
private String description;
/**
* 订单对应产品id
*/
@ExcelProperty(value = {"产品ID"}, index = 2)
private Integer productId;
/**
* 支付方式描述,如:apple pay
*/
@ExcelProperty(value = {"支付方式"}, index = 3)
private String payMethod;
/**
* create_time
*/
@ExcelProperty(value = {"时间"}, index = 4)
private String createTime;
/**
* update_time
*/
private String updateTime;
/**
* 产生订单的用户
*/
@ExcelProperty(value = {"用户ID"}, index = 5)
private Integer userId;
/**
* 支付状态:0 未支付、1支付成功支付完成、-1支付失败
*/
@ExcelProperty(value = {"支付状态"}, index = 6)
private String status;
/**
* 订单来源描述,如:ios 安卓
*/
@ExcelProperty(value = {"手机型号"}, index = 7)
private String platform;
/**
* 订单流水
*/
@ExcelProperty(value = {"订单流水号"}, index = 8)
private String flowNum;
/**
* 订单金额
*/
@ExcelProperty(value = {"金额"}, index = 9)
private BigDecimal price;
// @ExcelProperty(value = {"收据字段"}, index = 10)
private String receipt;
@ExcelProperty(value = {"APP来源"}, index = 10)
private String sources;
}
导出的模板定义好之后,接下来就是一些封装好的工具类的调用
- 查出我们需要导出的数据;
- 生成Excel文件名和sheet名称;
- 直接调用封装好的工具类导出文件即可;
我们来看下导出的效果
如果你的表头比较复杂,那么根据需求,你也可自行定义,例如如下这种复杂的表头,应该如何设置
首先要修改模板类,如果合并的单元格最大为2,那么所有的表格都需要设置为2,不合并的单元格用空字符串填充,需要合并的单元格将合并部分写上相同的名称,并且排列的序号要连续,不能分开。
我们来看下导出的效果,这样就可以满足我们平时开发需要的excel导出功能。简单易上手。
工具类:
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener; import java.util.ArrayList;
import java.util.List; /**
* 监听类,可以自定义
*
* @author liuyi
* @Created 2019-7-18 18:01:53
**/
public class ExcelListener extends AnalysisEventListener { /**
* 自定义用于暂时存储data。
* 可以通过实例获取该值
*/
private List<Object> datas = new ArrayList<>(); /**
* 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
*/
@Override
public void invoke(Object object, AnalysisContext context) {
//数据存储到list,供批量处理,或后续自己业务逻辑处理。
datas.add(object);
//根据业务自行 do something
doSomething();
/*
如数据过大,可以进行定量分批处理
if(datas.size()<=100){
datas.add(object);
}else {
doSomething();
datas = new ArrayList<Object>();
}
*/
} /**
* 根据业务自行实现该方法
*/
private void doSomething() {
} @Override
public void doAfterAllAnalysed(AnalysisContext context) {
/*
datas.clear();
解析结束销毁不用的资源
*/
} public List<Object> getDatas() {
return datas;
} public void setDatas(List<Object> datas) {
this.datas = datas;
}
}
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Font;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.TableStyle;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.mochu.exception.ExcelException;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List; /**
* Excel工具类
*
* @author liuyi
* @Created 2019-7-18 18:01:53
**/
public class ExcelUtil {
/**
* 读取 Excel(多个 sheet)
*
* @param excel 文件
* @param rowModel 实体类映射,继承 BaseRowModel 类
* @return Excel 数据 list
*/
public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel) {
ExcelListener excelListener = new ExcelListener();
ExcelReader reader = getReader(excel, excelListener); if (reader == null) {
return null;
} for (Sheet sheet : reader.getSheets()) {
if (rowModel != null) {
sheet.setClazz(rowModel.getClass());
}
reader.read(sheet);
} return excelListener.getDatas();
} /**
* 读取某个 sheet 的 Excel
*
* @param excel 文件
* @param rowModel 实体类映射,继承 BaseRowModel 类
* @param sheetNo sheet 的序号 从1开始
* @return Excel 数据 list
*/
public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo) {
return readExcel(excel, rowModel, sheetNo, 1);
} /**
* 读取某个 sheet 的 Excel
*
* @param excel 文件
* @param rowModel 实体类映射,继承 BaseRowModel 类
* @param sheetNo sheet 的序号 从1开始
* @param headLineNum 表头行数,默认为1
* @return Excel 数据 list
*/
public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo, int headLineNum) {
ExcelListener excelListener = new ExcelListener();
ExcelReader reader = getReader(excel, excelListener); if (reader == null) {
return null;
} reader.read(new Sheet(sheetNo, headLineNum, rowModel.getClass())); return excelListener.getDatas();
} /**
* 导出 Excel :一个 sheet,带表头
*
* @param response HttpServletResponse
* @param list 数据 list,每个元素为一个 BaseRowModel
* @param fileName 导出的文件名
* @param sheetName 导入文件的 sheet 名
* @param object 映射实体类,Excel 模型
*/
public static void writeExcel(HttpServletResponse response, List<? extends BaseRowModel> list, String fileName,
String sheetName, BaseRowModel object) {
ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
Sheet sheet = new Sheet(1, 0, object.getClass());
sheet.setSheetName(sheetName); TableStyle tableStyle = new TableStyle();
tableStyle.setTableContentBackGroundColor(IndexedColors.WHITE);
Font font = new Font();
font.setFontHeightInPoints((short) 9);
tableStyle.setTableHeadFont(font);
tableStyle.setTableContentFont(font);
sheet.setTableStyle(tableStyle); writer.write(list, sheet);
writer.finish();
} /**
* 导出 Excel :多个 sheet,带表头
*
* @param response HttpServletResponse
* @param list 数据 list,每个元素为一个 BaseRowModel
* @param fileName 导出的文件名
* @param sheetName 导入文件的 sheet 名
* @param object 映射实体类,Excel 模型
*/
public static ExcelWriterFactory writeExcelWithSheets(HttpServletResponse response,
List<? extends BaseRowModel> list, String fileName,
String sheetName, BaseRowModel object) {
ExcelWriterFactory writer = new ExcelWriterFactory(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
Sheet sheet = new Sheet(1, 0, object.getClass());
sheet.setSheetName(sheetName);
sheet.setTableStyle(getTableStyle());
writer.write(list, sheet); return writer;
} /**
* 导出融资还款情况表
*
* @param response
* @param list
* @param fileName
* @param sheetName
* @param object
*/
public static void writeFinanceRepayment(HttpServletResponse response, List<? extends BaseRowModel> list,
String fileName, String sheetName, BaseRowModel object) {
ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
Sheet sheet = new Sheet(1, 0, object.getClass());
sheet.setSheetName(sheetName);
sheet.setTableStyle(getTableStyle());
writer.write(list, sheet); for (int i = 1; i <= list.size(); i += 4) {
writer.merge(i, i + 3, 0, 0);
writer.merge(i, i + 3, 1, 1);
} writer.finish();
} /**
* 导出文件时为Writer生成OutputStream
*/
private static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
//创建本地文件
fileName = fileName + ".xls"; try {
fileName = new String(fileName.getBytes(), "ISO-8859-1");
response.addHeader("Content-Disposition", "filename=" + fileName); return response.getOutputStream();
} catch (Exception e) { throw new ExcelException("导出异常!");
}
} /**
* 返回 ExcelReader
*
* @param excel 需要解析的 Excel 文件
* @param excelListener new ExcelListener()
*/
private static ExcelReader getReader(MultipartFile excel, ExcelListener excelListener) {
String filename = excel.getOriginalFilename(); if (filename == null || (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx"))) {
throw new ExcelException("文件格式错误!");
}
InputStream inputStream; try {
inputStream = new BufferedInputStream(excel.getInputStream()); return new ExcelReader(inputStream, null, excelListener, false);
} catch (IOException e) {
e.printStackTrace();
} return null;
} /**
* 资金收支导出 Excel :一个 sheet,带表头
*
* @param response HttpServletResponse
* @param list 数据 list,每个元素为一个 BaseRowModel
* @param fileName 导出的文件名
* @param sheetName 导入文件的 sheet 名
* @param object 映射实体类,Excel 模型
*/
public static void exportFundBudgetExcel(HttpServletResponse response, List<? extends BaseRowModel> list,
String fileName, String sheetName, BaseRowModel object) throws IOException {
ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
Sheet sheet = new Sheet(1, 0, object.getClass());
sheet.setSheetName(sheetName);
sheet.setTableStyle(getTableStyle()); writer.write(list, sheet);
writer.merge(2, 3, 0, 0);
writer.merge(4, 13, 0, 0);
writer.merge(14, 14, 0, 1);
writer.finish();
} /**
* 读取Excel表格数据,封装成实体
*
* @param inputStream
* @param clazz
* @param sheetNo
* @param headLineMun
* @return
*/
public static Object readExcel(InputStream inputStream, Class<? extends BaseRowModel> clazz, Integer sheetNo,
Integer headLineMun) {
if (null == inputStream) { throw new NullPointerException("the inputStream is null!");
} ExcelListener listener = new ExcelListener();
ExcelReader reader = new ExcelReader(inputStream, valueOf(inputStream), null, listener);
reader.read(new Sheet(sheetNo, headLineMun, clazz)); return listener.getDatas();
} /**
* 根据输入流,判断为xls还是xlsx,该方法原本存在于easyexcel 1.1.0 的ExcelTypeEnum中。
*/
public static ExcelTypeEnum valueOf(InputStream inputStream) {
try {
FileMagic fileMagic = FileMagic.valueOf(inputStream); if (FileMagic.OLE2.equals(fileMagic)) {
return ExcelTypeEnum.XLS;
} if (FileMagic.OOXML.equals(fileMagic)) {
return ExcelTypeEnum.XLSX;
} throw new ExcelException("excelTypeEnum can not null"); } catch (IOException e) {
throw new RuntimeException(e);
}
} /**
* 设置全局样式
*
* @return
*/
private static TableStyle getTableStyle() {
TableStyle tableStyle = new TableStyle(); tableStyle.setTableContentBackGroundColor(IndexedColors.WHITE);
Font font = new Font();
font.setBold(true);
font.setFontHeightInPoints((short) 9);
tableStyle.setTableHeadFont(font);
Font fontContent = new Font();
fontContent.setFontHeightInPoints((short) 9);
tableStyle.setTableContentFont(fontContent); return tableStyle;
}
}
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum; import java.io.IOException;
import java.io.OutputStream;
import java.util.List; /**
*ExcelWriterFactory 工具类
* @author liuyi
* @Created 2019-7-18 18:01:53
**/
public class ExcelWriterFactory extends ExcelWriter {
private OutputStream outputStream;
private int sheetNo = 1; public ExcelWriterFactory(OutputStream outputStream, ExcelTypeEnum typeEnum) {
super(outputStream, typeEnum);
this.outputStream = outputStream;
} public ExcelWriterFactory write(List<? extends BaseRowModel> list, String sheetName, BaseRowModel object) {
this.sheetNo++;
try {
Sheet sheet = new Sheet(sheetNo, 0, object.getClass());
sheet.setSheetName(sheetName);
this.write(list, sheet);
}
catch(Exception ex) {
ex.printStackTrace();
try {
outputStream.flush();
}
catch(IOException e) {
e.printStackTrace();
}
}
return this;
} @Override
public void finish() {
super.finish();
try {
outputStream.flush();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
导入
其实在提供的那几个工具类中已经有了导入的方法,只需要直接调用即可。下面我们来简单演示一下,如何导入。我们先看下Controller是如何写的
@PostMapping("/import/order")
public ResultMsg import_order(MultipartFile excel) {
Object objList = ExcelUtil.readExcel(excel, new OrderExcelBO(), 1, 1);
if (objList == null) {
return ResultMsg.fail(500, "导入的数据不能为空");
}
List orderList = (List) objList;
if (orderList == null || orderList.size() <= 0) {
return ResultMsg.fail(500, "导入的数据不能为空");
}
orderList.forEach(System.out::println);
return ResultMsg.success();
}
我们主要再看下readExcel()方法是如何写的
/**
* 读取某个 sheet 的 Excel
*
* @param excel 文件
* @param rowModel 实体类映射,继承 BaseRowModel 类
* @param sheetNo sheet 的序号 从1开始
* @param headLineNum 表头行数,默认为1
* @return Excel 数据 list
*/
public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo, int headLineNum) {
ExcelListener excelListener = new ExcelListener();
ExcelReader reader = getReader(excel, excelListener); if (reader == null) {
return null;
} reader.read(new Sheet(sheetNo, headLineNum, rowModel.getClass())); return excelListener.getDatas();
}
在底层的方法我就不贴出来了,我大家可在()文章里面找到需要的工具类,我们就直接看下运行结果。
导出结果
那么数据都已经打印出来了,那么存入数据库就超级简单了。
SpringBoot整合easyexcel实现Excel的导入与导出的更多相关文章
- SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多
关于封面:晚饭后回自习室的路上 Easyexcel 官方文档 Easyexcel | github 前言 最近也是在写的一个小练习中,需要用到这个.趁着这次就将写个整合的Demo给大家. 希望能够让大 ...
- springboot整合easyexcel实现Excel导入导出
easyexcel:快速.简单避免OOM的java处理Excel工具 Java解析.生成Excel比较有名的框架有Apache poi.jxl.但他们都存在一个严重的问题就是非常的耗内存,poi有一套 ...
- SpringBoot中关于Excel的导入和导出
前言 由于在最近的项目中使用Excel导入和导出较为频繁,以此篇博客作为记录,方便日后查阅.本文前台页面将使用layui,来演示对Excel文件导入和导出的效果.本文代码已上传至我的gitHub, ...
- excel的导入与导出---通用版
excel的导入与导出---通用版 web项目关于导入导出的业务场景很常见,最近我就又遇到了这个业务场景.这次将最近半个月做的导入导出总结一下 使用的pom如下,主要还是阿里巴巴的easyexcel依 ...
- .net数据库实现Excel的导入与导出
.net数据库实现Excel的导入与导出 参考路径:https://www.cnblogs.com/splendidme/archive/2012/01/05/2313314.html 1.defau ...
- SpringCloud微服务实战——搭建企业级开发框架(三十):整合EasyExcel实现数据表格导入导出功能
批量上传数据导入.数据统计分析导出,已经基本是系统必不可缺的一项功能,这里从性能和易用性方面考虑,集成EasyExcel.EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项 ...
- C#中Excel的导入和导出的几种基本方式
在上一篇(http://www.cnblogs.com/fengchengjushi/p/3369386.html)介绍过,Excel也是数据持久化的一种实现方式.在C#中.我们常常会与Excel文件 ...
- Excel报表开发(主要讲Excel的导入和导出)
一.Excel数据导入 连接字符串Excel2003版: OleDbConnection conn = new OleDbConnection("provider=Microsoft.Jet ...
- java实现Excel的导入、导出
一.Excel的导入 导入可采用两种方式,一种是JXL,另一种是POI,但前者不能读取高版本的Excel(07以上),后者更具兼容性.由于对两种方式都进行了尝试,就都贴出来分享(若有错误,请给予指正) ...
随机推荐
- 判断101-200之间有多少个素数,并输出所有素数,方法:用一个数分别去除2到sqrt(这个数),如果能被整除, 则表明此数不是素数,反之是素数。
<?php$sum=0;for($i=101;$i<=200;$i++){ for($j=2;$j<=sqrt($i);$j++) { if($i%$j==0 ...
- 肖哥讲jquery:
jquery 是一个模块 一个库 js封装的一个库 导入jq <script src="jquery.js"></script> <script ...
- php 学习笔记之关于时区的那点事
科普一下什么是时区 众所周知,地球绕着太阳转的同时也会自转,因此同一时刻不同地区所接收到太阳照射的情况不同,所以有的地区是日出,有的地区是日落,还有的地区可能是黑夜. 既然地球上的不同地区时间不同,那 ...
- Java并发编程核心知识体系精讲
第1章 开宗明义[不看错过一个亿]本章一连串设问:为什么学并发编程?学并发编程痛点?谁适合学习本课?本课程包含内容和亮点?首先4大个理由告诉你为什么要学,其实源于JD岗位要求就不得不服了.其次5个痛点 ...
- nowcoder941B 弹钢琴
题目链接 思路 首先按照音色排个序,顺便离散化一下音高. 用\(h[i]\)表示第\(i\)个键的音高,用\(w[i]\)表示第\(i\)个键的春希度. 朴素\(dp\) \(f[i][j]\)表示前 ...
- [译][ABP vNext]ABP CLI,v0.18版本的新模板和其他功能
ABP CLI,v0.18版本的新模板和其他功能 ABP v0.18已发布, 包含解决的70+个issue,500+次提交 网站更改 abp.io网站完全更新以突出ABP框架的目标和重要功能.文档和博 ...
- ORB-SLAM2初步(源码逻辑分析)
今天主要是梳理一下ORB-SLAM2源码的逻辑关系,GitHub和泡泡机器人上有很好的注释版本(吴博),大神请(轻)板砖. 一.文件 如图所示,Examples里面存放的分别是基于单目.双目.RGBD ...
- webrtc笔记(3): 多人视频通讯常用架构Mesh/MCU/SFU
问题:为什么要搞这么多架构? webrtc虽然是一项主要使用p2p的实时通讯技术,本应该是无中心化节点的,但是在一些大型多人通讯场景,如果都使用端对端直连,端上会遇到很带宽和性能的问题,所以就有了下图 ...
- python合并视频
视频合并 输入为:包含有视频的文件夹(注意路径:如 D:\\moves\\joy 双斜杠).合并后内容的名字如(我的合并视频 不用加.mp4) 输出为:我的合并视频.mp4+一个音频 ...
- DDR基础知识
1.前言 DDR的全称为Double Data Rate SDRAM,也就是双倍速率的SDRAM,SDRAM在一个CLK周期传输一次数据,而DDR在一个CLK周期传输两次数据,分别在上升沿和下降沿各传 ...