因为最近项目用到 把数据库的数据导入到Excel中,所以就用了此工具… Apache 的 poi 导出内存占用非常高,尤其多人同时导出数据的时候,性能会收到冲击…所以采用更轻巧的EasyExcel工具.
EasyExcel 是阿里巴巴提供的.最大的特点就是使用内存少,易上手…使用简单…
<!-- 解析excel -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency><!-- 阿里巴巴EasyExcel-->
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>1.1.2-beta4</version>
</dependency>
ExcelUtil | 主要的工具类,可以直接调用该工具类的方法完成 Excel 的读或者写 |
---|---|
ExcelListener | 监听类,可以根据需要与自己的情况,自定义处理获取到的数据,我这里只是简单地把数据添加到一个 List 里面 |
ExcelWriterFactroy | 用于导出多个 sheet 的 Excel,通过多次调用 write 方法写入多个 sheet |
ExcelException | 捕获相关 Exception |
读取 Excel 时只需要调用 ExcelUtil.readExcel() 方法
作为映射实体类,通过 @ExcelProperty 注解与 index 变量可以标注成员变量所映射的列,同时不可缺少 setter 方法
@GetMapping(value = "readExcel")
public Object readExcel(MultipartFile excel) {
return ExcelUtil.readExcel(excel, new OrderExcelVM());
}
导入的实体类代码
public class OrderExcelVM extends BaseRowModel {
@ExcelProperty(index = 0)
private String orderSn;
@ExcelProperty(index = 1)
//@DateTimeFormat( iso = DateTimeFormat.ISO.DATE_TIME)
private String addTime;
@ExcelProperty(index = 2)
private BigDecimal orderAmount;
@ExcelProperty(index = 3)
private BigDecimal orderActivityMoney;
.
导出的 Excel 只拥有一个 sheet 只需要调用 ExcelUtil.writeExcel() 方法:
@GetMapping(value = "writeExcel")
public void writeExcel(HttpServletResponse response) throws IOException {
List<OrderExcelVM> list = orderService.getList();//获取的订单数据
String time = DateUtils.stampToDate(new Long(System.currentTimeMillis()/1000).intValue());
time = time.replaceAll("-","");
time = time.replaceAll(":","");
time = time.replaceAll(" ","");
//excel的名称
String fileName = "导出订单"+time;
String sheetName = "订单列表";
ExcelUtil.writeExcel(response, list, fileName, sheetName, new OrderExcelVM());
}
fileName,sheetName 分别是导出文件的文件名和 sheet 名,new ExportInfo() 为导出数据的映射实体对象,list 为导出数据。
对于映射实体类,可以根据需要通过 @ExcelProperty 注解自定义表头,当然同样需要继承 BaseRowModel 类,如:
public class OrderExcelVM extends BaseRowModel {
//index 是导出的表头对应的列 value 为列名,index 为列的序号
@ExcelProperty(value = "订单编号",index = 0)
private String orderSn;
@ExcelProperty(value = "下单时间",index = 1)
//@DateTimeFormat( iso = DateTimeFormat.ISO.DATE_TIME)
private String addTime;
@ExcelProperty(value ="订单总金额",index = 2)
private BigDecimal orderAmount;
@ExcelProperty(value ="活动总金额",index = 3)
private BigDecimal orderActivityMoney;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.yshuadmin.common.exception.YSException;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
/**
* Created with IntelliJ IDEA
*
* @Author yuanhaoyue swithaoy@gmail.com
* @Description 工具类
* @Date 2018-06-06
* @Time 14:07
*/
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);
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 ExcelWriterFactroy writeExcelWithSheets(HttpServletResponse response, List<? extends BaseRowModel> list,
String fileName, String sheetName, BaseRowModel object) {
ExcelWriterFactroy writer = new ExcelWriterFactroy(getOutputStream(fileName, response), ExcelTypeEnum.XLSX);
Sheet sheet = new Sheet(1, 0, object.getClass());
sheet.setSheetName(sheetName);
writer.write(list, sheet);
return writer;
}
/**
* 导出文件时为Writer生成OutputStream
*/
private static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
//创建本地文件
String filePath = fileName + ".xlsx";
File dbfFile = new File(filePath);
try {
if (!dbfFile.exists() || dbfFile.isDirectory()) {
dbfFile.createNewFile();
}
fileName = new String(filePath.getBytes(), "ISO-8859-1");
response.addHeader("Content-Disposition", "filename=" + fileName);
return response.getOutputStream();
} catch (IOException e) {
throw new YSException( "创建文件失败!");
}
}
/**
* 返回 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 YSException("文件格式错误!");
}
InputStream inputStream;
try {
inputStream = new BufferedInputStream(excel.getInputStream());
return new ExcelReader(inputStream, null, excelListener, false);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
/**
* Created with IntelliJ IDEA
*
* @Author yuanhaoyue swithaoy@gmail.com
* @Description 监听类,可以自定义
* @Date 2018-06-05
* @Time 16:58
*/
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