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以上),后者更具兼容性.由于对两种方式都进行了尝试,就都贴出来分享(若有错误,请给予指正) ...
随机推荐
- Vue+cordova开发App
Vue+cordova开发App https://www.imooc.com/article/70062
- DHCP服务基本搭建
DHCP原理 DHCP租约四部曲: A:客户端进行IP请求 当一个DHCP客户机启动时,会自动将自己的IP地址配置成0.0.0.0,由于使用0.0.0.0不能进行正常通信,所以客户机就必须通过DHCP ...
- day82_10_31celery的使用
1.缓存 当一些数据需要固定地且频繁访问数据库时,需要使用到接口缓存. 以轮播图为例,每个用户都会访问首页,首页的轮播图长时间不会改变,所以可以使用cache,将固定数据保存到缓存中(redis),第 ...
- 【转】springboot结合swagger生成接口文档
前后台分离的开发渐渐已成趋势.那么前后端的沟通就成了问题,包括移动端,web端.如果有一个东西在我们写完代码的时候,自动将接口的所有注释,调用文档提供出来,是不是一件很美好的事情.那就是使用swagg ...
- LeetCode 674. Longest Continuous Increasing Subsequence最长连续递增序列 (C++/Java)
题目: Given an unsorted array of integers, find the length of longest continuous increasing subsequenc ...
- nanopor软件列表
1.软件
- Avalon的小故事 (1)
我:这个游戏真没意思,我为什么要玩这种东西 A:你渡过了前期才能发现这个游戏的乐趣 我:那我为什么不换一个游戏玩呢?换一个开头就让人欲罢不能的游戏? B:你这是逃避!你个懦夫! 我:我连自己选择游戏的 ...
- vscode中关于launch.json和tasks.json的变量说明
vscode是一个轻量级的文本编辑器,但是它的拓展插件可以让他拓展成功能齐全的IDE,这其中就靠的是tasks.json和launch.json的配置 这两个json文件的相关变量是vscode特有的 ...
- orchard 中文文档 中英对照版
ORCHARD CMS a free, open source, community-focused Content Management System built on the ASP.NET MV ...
- tsar使用说明
常用命令 tsar --nginx --live -i 1 查询1秒的状态每秒采样一次 系统模块 cpu 字段含义 user: 表示CPU执行用户进程的时间,通常期望用户空间CPU越高越好. ...