简介:导出报表是目前常有功能,当数据量特别大的时候会内存溢出和卡顿页面,poi的操作方式仍然存在内存占用过大的问题,以及存在内存溢出的隐患。无意间查询到阿里开源的EasyExcel框架,发现可以将解析的EXCEL的内存占用控制在KB级别,并且绝对不会内存溢出(内部实现待研究),还有就是速度极快, 大概100W条记录,十几个字段, 只需要70秒即可完成下载。果断研究阿里开源的EasyExcel. 并封装了一个EasyExcelUtil
EasyExcel的传送门:https://github.com/alibaba/easyexcel
EasyExcel的官方文档:https://alibaba-easyexcel.github.io/index.html
Maven依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.3</version>
</dependency>
自己基于springboot2.1.4+exsyexcel搭建的一个简单的demo
bean层
package com.easyexcel.demo.entity;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @author Kodak
* @version Id: MsgClient.java, v 0.1 2019/12/6 18:17 lai_kd Exp $$
*/
@Data
//设置列宽
//@ContentRowHeight(20) //设置样式
public class MsgClient implements Serializable {
//ExcelProperty 设置表头
@ExcelProperty(value = {"主标题","生日"}, index = 0)
@ColumnWidth(20)
private Date birthday;
@ExcelProperty(value = {"主标题","名字"}, index = 1)
@ColumnWidth(10)
private String clientName;
@ExcelProperty(value = "手机", index = 2)
@ColumnWidth(50)
private String cientPhone;
@ExcelProperty(value = "创建人", index = 3)
private String createBy;
@ExcelProperty(value = "ID", index = 4)
private int id;
@ExcelProperty(value = "备注", index = 5)
@ExcelIgnore //设置改列不导出
private String remark;
}
service
package com.easyexcel.demo.service;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author Kodak
* @version Id: EasyExcelService.java, v 0.1 2019/12/8 16:21 lai_kd Exp $$
*/
public interface EasyExcelService<T> {
/**
* 单sheet页
* @param list 结果集
* @param c 表头 也就是实体化对象的类
* @param fileName 文件名称
* @param sheetName sheet页名称
* @throws IOException 异常
*/
void writeExce(List<T> list, Class<?> c, String fileName, String sheetName) throws IOException;
/**
* 多sheet页
* @param list 结果集
* @param className 表头 也就是实体化对象的类
* @param fileName 文件名称
* @param sheetName sheet页名称
* @param sheet sheet页的个数
* @throws IOException 异常
* 注意多sheet必须要和多个class对应
*/
void writeExcelSheets(List[] list, Class[] className, String fileName, String[] sheetName, int sheet) throws IOException;
/**
* 动态表头
* @param list 结果集
* @param fileName 文件名称
* @param sheetName sheet页名称
* @param sheet sheet页数
* @throws IOException IO异常
*/
void dynamicHeadWrite(List list, String fileName, String sheetName, int sheet)throws IOException;
/**
* 根据模板写入
* @param list 结果集
* @param fileName 文件名称
* @param sheetName sheet页名称
* @param sheet sheet页数
* @throws IOException IO异常
*/
void templateWrite(List list, String fileName, String sheetName, int sheet, String templatePath)throws IOException;
/**
* 边读边写 单个list写入多个sheet页
* @param c 表头
* @param fileName 文件名称
* @param sheetName 页名称
*/
void writeSingleListOrSheet(Class c, String fileName, String sheetName);
/**
*
* @param fileName
* @param sheetName
* @param list
*/
void repeatedWrite(String fileName, String sheetName, List list);
void noModleWrite(String fileName, List head, List list);
void noModel(String fileName, String sheetName, Map map, List list);
void repeated(String fileName, String sheetName, List list, Map map);
}
impl
package com.easyexcel.demo.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.easyexcel.demo.dao.MarketVerifyInfoMapper;
import com.easyexcel.demo.entity.MarketVerifyInfoDO;
import com.easyexcel.demo.entity.MsgClient;
import com.easyexcel.demo.service.EasyExcelService;
import com.easyexcel.demo.service.EasyExcelService2;
import com.easyexcel.demo.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author Kodak
* @version Id: EasyExcelImpl.java, v 0.1 2019/12/8 16:21 lai_kd Exp $$
*/
@Service
@Slf4j
public class EasyExcelImpl<T> implements EasyExcelService {
/**
* 线程池服务
*/
private final TaskExecutor taskExecutor;
@Autowired
public EasyExcelImpl2(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
/**
* 单sheet页
* @param list 结果集
* @param c 表头 也就是实体化对象的类
* @param fileName 文件名称
* @param sheetName sheet页名称
* @throws IOException 异常
*/
@Override
public void writeExce(List list, Class c,String fileName,String sheetName) throws IOException {
try (OutputStream out = new FileOutputStream(fileName);) {
ExcelWriter excelWriter = EasyExcel.write(fileName,c).build();
// 这里注意 如果同一个sheet只要创建一次
WriteSheet writeSheet = EasyExcel.writerSheet(fileName).build();
writeSheet.setSheetName(sheetName);
for (Object o : list) {
Class<?> cls = o.getClass() ;
String o1 = cls.newInstance().getClass().getName();
String[] split = o1.split("\\.");
//截取最后的类名然后自己在手动转换
o1=split[split.length-1];
if (o1.equals("MsgClient")){
MsgClient msgClient=(MsgClient)o;
msgClient.setCientPhone("牛逼!!");
}
}
Runnable r2=()-> excelWriter.write(list, writeSheet);
excelWriter.finish();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
/**
* 多sheet页
* @param list 结果集
* @param className 表头 也就是实体化对象的类
* @param fileName 文件名称
* @param sheetName sheet页名称
* @param sheet sheet页的个数
* @throws IOException 异常
* 注意多sheet必须要和多个class对应
*/
@Override
public void writeExcelSheets(List[] list,Class[] className, String fileName, String[] sheetName, int sheet)throws IOException {
try (OutputStream out = new FileOutputStream(fileName);) {
// 方法3 如果写到不同的sheet 不同的对象
ExcelWriter excelWriter =null;
// 这里 指定文件
excelWriter = EasyExcel.write(fileName).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < sheet; i++) {
// 每次都要创建writeSheet 这里注意必须指定sheetNo。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变
WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetName[i]).head(className[i]).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
ExcelWriter finalExcelWriter = excelWriter;
int finalI = i;
System.out.println("--->"+list[i].toString());
new Thread(()-> finalExcelWriter.write(list[finalI], writeSheet)).run();
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
}
/**
* 自定义表头
* @param list 结果集
* @param fileName 文件名称
* @param sheetName sheet页名称
* @param sheet sheet页数
* @throws IOException IO异常
*/
@Override
public void dynamicHeadWrite(List list, String fileName, String sheetName, int sheet) throws IOException {
List<List<String>> listDate = new ArrayList<List<String>>();
List<String> listHead=new ArrayList<>();
listHead.add("A");
List<String> listHead1=new ArrayList<>();
listHead1.add("B");
List<String> listHead2=new ArrayList<>();
listHead2.add("C");
listDate.add(listHead);
listDate.add(listHead1);
listDate.add(listHead2);
EasyExcel.write(fileName)
// 这里放入动态头
.head(listDate).sheet(sheetName)
// 当然这里数据也可以用 List<List<String>> 去传入
.doWrite(list);
//写入sheet页 和sheetName名称
EasyExcel.writerSheet(sheet, sheetName).build();
}
/**
* 根据模板写入
* @param list 结果集
* @param fileName 文件名称
* @param sheetName sheet页名称
* @param sheet sheet页数
* @param templatePath 模板文件路径
* @throws IOException
*/
@Override
public void templateWrite(List list, String fileName, String sheetName, int sheet,String templatePath) throws IOException {
taskExecutor.execute(()->EasyExcel.write(fileName).withTemplate(templatePath).sheet().doWrite(list));
}
@Override
public void writeSingleListOrSheet(Class c, String fileName, String sheetName) {
// 方法2 如果写到不同的sheet 同一个对象
// // 这里 指定文件
// ExcelWriter excelWriter = EasyExcel.write(fileName, MsgClient.class).build();
// // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
// for (int i = 0; i < 5; i++) {
// // 每次都要创建writeSheet 这里注意必须指定sheetNo
// WriteSheet writeSheet = EasyExcel.writerSheet(i, i+"模板").build();
// // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
// List<MsgClient> data = data(String.valueOf(i));
// excelWriter.write(data, writeSheet);
// }
// /// 千万别忘记finish 会帮忙关闭流
// excelWriter.finish();
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = EasyExcel.write(fileName, MsgClient.class).build();
// 这里注意 如果同一个sheet只要创建一次
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
for (int i = 0; i < 5; i++) {
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
List<MsgClient> data = data(String.valueOf(i));
new Thread(()->excelWriter.write(data, writeSheet)).run();
// excelWriter.write(data, writeSheet);
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
private List<MsgClient> data(String str) {
List<MsgClient> list = new ArrayList<MsgClient>();
for (int i = 0; i < Integer.parseInt(str)+100; i++) {
MsgClient msgClient=new MsgClient();
msgClient.setBirthday(new Date());
msgClient.setClientName("A");
msgClient.setCientPhone("1555");
msgClient.setCreateBy("kodak");
msgClient.setId(i);
msgClient.setRemark("备注" + i);
list.add(msgClient);
}
return list;
}
/**
* 直接写入
* @param list 集合
* @param excelWriter
* @param writeSheet
*/
public void Write(List list,ExcelWriter excelWriter,WriteSheet writeSheet){
excelWriter.write(list, writeSheet);
excelWriter.finish();
}
/**
*单写
* @param fileName 文件名
* @param sheetName sheet页名臣
* @param list 数据集合
*/
@Override
public void repeatedWrite(String fileName,String sheetName,List list){
try (OutputStream out = new FileOutputStream(fileName);) {
ExcelWriter excelWriter = EasyExcel.write(fileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet( sheetName).build();
Write(list,excelWriter , writeSheet);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void noModleWrite(String fileName,List head,List list){
EasyExcel.write(fileName).head(head).sheet("模板").doWrite(list);
}
@Override
public void noModel(String fileName, String sheetName, Map map, List list){
ExcelWriter excelWriter = EasyExcel.write(fileName,MsgClient.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();
excelWriter.write(getHeadList(map), writeSheet);
excelWriter.write(list,writeSheet );
excelWriter.finish();
}
private static List getHeadList(Map map){
List<List<String>> list = new ArrayList<List<String>>();
List<String> head0 = new ArrayList<String>();
StringBuffer buffer=new StringBuffer();
Date startDate = DateUtil.parse(DateUtil.format((Date) map.get("StartDate"), DateUtil.STANDARD_PATTERN), DateUtil.STANDARD_PATTERN);
buffer.append("对账单日期"+ DateUtil.format(startDate, DateUtil.DATE_SHOW_FORMAT)+"——"
+DateUtil.format(DateUtil.getLastDayOfMonth(startDate), DateUtil.DATE_SHOW_FORMAT)+" 单位:元");
head0.add(buffer.toString());
list.add(head0);
return list;
}
/**
* 如果写到不同的sheet 不同的对象
*
* @param fileName 文件名称
*/
@Override
public void repeated(String fileName, String path, List list,Map map) {
//
// WriteCellStyle headWriteCellStyle = new WriteCellStyle();
// headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
//
// HorizontalCellStyleStrategy horizontalCellStyleStrategy =
// new HorizontalCellStyleStrategy(headWriteCellStyle,new WriteCellStyle());
//内容的策略
// WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
// WriteFont contentWriteFont = new WriteFont();
// // 字体大小
// contentWriteFont.setFontHeightInPoints((short)15);
// contentWriteFont.setColor((short)000000);
// // 背景绿色
// contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
// contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// contentWriteCellStyle.setWriteFont(contentWriteFont);
// HorizontalCellStyleStrategy horizontalCellStyleStrategy1 =
// new HorizontalCellStyleStrategy(new WriteCellStyle(),contentWriteCellStyle);
ExcelWriter excelWriter = EasyExcel.write(fileName, MsgClient.class).build();
// 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了
WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();
// 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要
WriteTable writeTable0 = EasyExcel.writerTable(0).needHead(Boolean.FALSE).build();
WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build();
// 第一次写入会创建头
excelWriter.write(getHeadList(map), writeSheet, writeTable0);
// 第二次写如也会创建头,然后在第一次的后面写入数据
excelWriter.write(list, writeSheet, writeTable1);
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
// ExcelWriter excelWriter = EasyExcel.write(fileName,MsgClient.class).build();
// WriteSheet sheet = EasyExcel.writerSheet().head(getHeadList(map)).build();
// WriteSheet writeSheet = EasyExcel.writerSheet().build();
// excelWriter.write(getHeadList(map), sheet);
// excelWriter.write(list,writeSheet );
// WriteSheet writeSheet=EasyExcel.writerSheet(path+"i").build();
// excelWriter.write(getHeadList(map), writeSheet);
// excelWriter.write(list, writeSheet);
// WriteSheet writeSheet1 = EasyExcel.writerSheet(1,path).head(MsgClient.class).build();
// WriteSheet writeSheet2 = EasyExcel.writerSheet(2,path+"i").head(MsgClient.class).build();
// excelWriter.write(list,writeSheet1 );
// excelWriter.write(list,writeSheet2);
// excelWriter.finish();
}
/**
* 单线程模板导出
*
* @param list 结果集
* @param fileName 文件名称
* @param templatePath 模板文件路径
*/
public void templateWrite(List list, String fileName,String templatePath){
new Thread(() -> EasyExcel.write(fileName).withTemplate(templatePath).sheet().doWrite(list));
}
/**
* 单个sheet页写边读编写
*
* @param c 表头
* @param fileName 文件名称
* @sheetName sheetName Sheet名称
*/
public void repeatedWrite(Class c, String fileName, String sheetName) {
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = EasyExcel.write(fileName, c).build();
// 这里注意 如果同一个sheet只要创建一次
WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来
for (int i = 0; i < 5; i++) {
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
// List<T> data = data();
// excelWriter.write(data, writeSheet);
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
/**
* 如果写到不同的sheet 同一个对象
*
* @param c 表头
* @param fileName 文件名称
* @param sheetName sheet页名称
* @param sheet sheet页面
*/
public void repeatedWrite(Class c, String fileName, String[] sheetName, int sheet) {
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = EasyExcel.write(fileName, c).build();
WriteSheet writeSheet;
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < sheet; i++) {
// 每次都要创建writeSheet 这里注意必须指定sheetNo
writeSheet = EasyExcel.writerSheet(i, sheetName[i]).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
// List<DemoData> data = data();
// excelWriter.write(data, writeSheet);
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
/**
* 如果写到不同的sheet 不同的对象
*
* @param c 表头
* @param fileName 文件名称
*/
public void repeatedWrite(Class[] c, String fileName) {
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = null;
WriteSheet writeSheet=null;
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < 5; i++) {
excelWriter= EasyExcel.write(fileName, c[i]).build();
// 每次都要创建writeSheet 这里注意必须指定sheetNo
writeSheet = EasyExcel.writerSheet(i, "Sheet"+i).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
// List<DemoData> data = data();
// excelWriter.write(data, writeSheet);
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
/**
* 不同集合不同对象 一次性查询 单线程导出
* @param list 集合对象要和class对应
* @param c 表头集合要与list对应
* @param fileName 文件名称
*/
public void repeatedWrite(List[] list,Class[] c, String fileName) {
try (OutputStream out = new FileOutputStream(fileName);) {
// 方法3 如果写到不同的sheet 不同的对象
ExcelWriter excelWriter = null;
// 这里 指定文件
excelWriter = EasyExcel.write(fileName).build();
// 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面
for (int i = 0; i < 2; i++) {
// 每次都要创建writeSheet 这里注意必须指定sheetNo。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变
WriteSheet writeSheet = EasyExcel.writerSheet(i, "Sheet"+i).head(c[i]).build();
// 分页去数据库查询数据 这里可以去数据库查询每一页的数据
ExcelWriter finalExcelWriter = excelWriter;
int finalI = i;
new Thread(() -> finalExcelWriter.write(list[finalI], writeSheet)).run();
}
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
controller
package com.easyexcel.demo.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.easyexcel.demo.entity.MsgClient;
import com.easyexcel.demo.entity.Test2;
import com.easyexcel.demo.service.EasyExcelService;
import com.easyexcel.demo.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.*;
/**
* @author lai_kd
* @version Id: CreateExcelDemo.java, v 0.1 2019/12/8 16:26 lai_kd Exp $$
*/
@RestController
@Slf4j
public class CreateExcelDemo {
private final EasyExcelService easyExcel;
private static final String fileName="C:\\data\\dataTemp\\CreateTest.xlsx";
@Autowired
public CreateExcelDemo(EasyExcelService easyExcel) {
this.easyExcel = easyExcel;
}
@RequestMapping("write")
public String write() throws IOException {
long stateTime = System.currentTimeMillis();
List<MsgClient> list = new ArrayList();
for (int i = 0; i < 100; i++) {
MsgClient msgClient = new MsgClient();
msgClient.setBirthday(new Date());
msgClient.setClientName("阿斯顿撒旦撒大苏打撒旦撒倒萨倒萨大苏打撒打算大苏打啊实打实的阿斯顿撒旦撒大苏打撒旦撒倒萨倒萨大苏打撒打算大苏打啊实打实的阿斯顿撒旦撒大苏打撒旦撒倒萨倒萨大苏打撒打算大苏打啊实打实的");
msgClient.setCientPhone("as");
msgClient.setCreateBy("kodak");
msgClient.setId(i);
msgClient.setRemark("备注" + i);
list.add(msgClient);
}
easyExcel.writeExce(list, MsgClient.class, fileName,"sheet1");
String endTime=System.currentTimeMillis() - stateTime + "ms";
log.info("导出的数据量是[{}],耗时[{}]",list.size(),endTime);
return "导出的数据量是"+list.size()+",耗时"+endTime;
}
@RequestMapping("writeSheets")
public String writeSheets() throws IOException {
long stateTime = System.currentTimeMillis();
List<MsgClient> list = new ArrayList();
for (int i = 0; i < 1; i++) {
MsgClient msgClient = new MsgClient();
msgClient.setBirthday(new Date());
msgClient.setClientName("A");
msgClient.setCientPhone("1555");
msgClient.setCreateBy("kodak");
msgClient.setId(i);
msgClient.setRemark("备注" + i);
list.add(msgClient);
}
String[] sheetName={"sheet1","sheet2"};
Class[] className={MsgClient.class,Test2.class};
List list1=new ArrayList();
list1.add("活动");
list1.add("活动1");
list1.add("活动2");
List[] lists={list,list1};
easyExcel.writeExcelSheets(lists, className, fileName,sheetName,2);
String endTime=System.currentTimeMillis() - stateTime + "ms";
log.info("导出的数据量是[{}],耗时[{}]",list.size(),endTime);
return "导出的数据量是"+list.size()+",耗时"+endTime;
}
@RequestMapping("dynamicHeadWrite")
public String dynamicHeadWrite() throws IOException {
long stateTime = System.currentTimeMillis();
List<MsgClient> list = new ArrayList();
for (int i = 0; i < 100; i++) {
MsgClient msgClient = new MsgClient();
msgClient.setBirthday(new Date());
msgClient.setClientName("A");
msgClient.setCientPhone("1555");
msgClient.setCreateBy("kodak");
msgClient.setId(i);
msgClient.setRemark("备注" + i);
list.add(msgClient);
}
easyExcel.dynamicHeadWrite(list, fileName, "Test", 1);
String endTime=System.currentTimeMillis() - stateTime + "ms";
log.info("导出的数据量是[{}],耗时[{}]",list.size(),endTime);
return "导出的数据量是"+list.size()+",耗时"+endTime;
}
@RequestMapping("templateWrite")
public String templateWrite() throws IOException {
long stateTime = System.currentTimeMillis();
List<MsgClient> list = new ArrayList();
for (int i = 0; i < 1000; i++) {
MsgClient msgClient = new MsgClient();
msgClient.setBirthday(new Date());
msgClient.setClientName("A");
msgClient.setCientPhone("1555");
msgClient.setCreateBy("kodak");
msgClient.setId(i);
msgClient.setRemark("备注" + i);
list.add(msgClient);
}
easyExcel.templateWrite(list, fileName, "Test", 1,"C:\\data\\dataTemp\\demo.xlsx");
String endTime=System.currentTimeMillis() - stateTime + "ms";
log.info("导出的数据量是[{}],耗时[{}]",list.size(),endTime);
return "导出的数据量是"+list.size()+",耗时"+endTime;
}
/**
* 同步的返回,不推荐使用,如果数据量大会把数据放到内存里面
*/
@RequestMapping("synchronousRead")
public void synchronousRead() throws IOException {
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
List<MsgClient> list = EasyExcel.read(fileName).head(MsgClient.class).sheet().doReadSync();
for (MsgClient msgClient : list) {
log.info("读取到数据:{}", JSON.toJSONString(msgClient));
}
for (int i = 0; i < 100; i++) {
MsgClient msgClient=new MsgClient();
msgClient.setBirthday(new Date());
msgClient.setClientName("A");
msgClient.setCientPhone("1555");
msgClient.setCreateBy("kodak");
msgClient.setId(i);
msgClient.setRemark("备注" + i);
list.add(msgClient);
easyExcel.writeExce(list,MsgClient.class ,fileName ,"Test" );
}
// 这里 也可以不指定class,返回一个list,然后读取第一个sheet 同步读取会自动finish
// List<Map<Integer, String>> listMap = EasyExcel.read(fileName).sheet().doReadSync();
// for (Map<Integer, String> data : listMap) {
// // 返回每条数据的键值对 表示所在的列 和所在列的值
// log.info("读取到数据:{}", JSON.toJSONString(data));
// }
}
@RequestMapping("writeSingleListOrSheet")
public String writeSingleListOrSheet(){
long stateTime = System.currentTimeMillis();
easyExcel.writeSingleListOrSheet(MsgClient.class, fileName,"test" );
String endTime=System.currentTimeMillis() - stateTime + "ms";
log.info("耗时[{}]",endTime);
return "耗时"+endTime;
}
@RequestMapping("writeSinge")
public String writeSinge(){
long stateTime = System.currentTimeMillis();
easyExcel.repeatedWrite(fileName, "可笑", getDateList());
String endTime=System.currentTimeMillis() - stateTime + "ms";
log.info("导出的数据量是[{}],耗时[{}]",getDateList().size(),endTime);
return "导出的数据量是"+getDateList().size()+",耗时"+endTime;
}
@RequestMapping("noModleWrite")
public String noModleWrite(){
long stateTime = System.currentTimeMillis();
Date startDate = DateUtil.parse("201910", DateUtil.MONTHS_PATTERN);
Date endDate = DateUtil.plusMonths(startDate, 1);
Map map=new HashMap();
map.put("StartDate", startDate);
map.put("EndDate", endDate);
easyExcel.noModel(fileName,"c" , map, getDateList());
String endTime=System.currentTimeMillis() - stateTime + "ms";
log.info("导出的数据量是[{}],耗时[{}]",getDateList().size(),endTime);
return "导出的数据量是"+getDateList().size()+",耗时"+endTime;
}
public List getDateList(){
List list=new ArrayList();
for (int i = 0; i < 100; i++) {
MsgClient msgClient=new MsgClient();
msgClient.setBirthday(new Date());
msgClient.setClientName("A");
msgClient.setCientPhone("1555");
msgClient.setCreateBy("kodak");
msgClient.setId(i);
msgClient.setRemark("备注" + i);
list.add(msgClient);
}
return list;
}
private static List getHreadList(Map map){
List<List<String>> list = new ArrayList<List<String>>();
List<String> head0 = new ArrayList<String>();
StringBuffer buffer=new StringBuffer();
Date startDate = DateUtil.parse(DateUtil.format((Date) map.get("StartDate"), DateUtil.STANDARD_PATTERN), DateUtil.STANDARD_PATTERN);
buffer.append("对账单日期"+ DateUtil.format(startDate, DateUtil.DATE_SHOW_FORMAT)+"——"
+DateUtil.format(DateUtil.getLastDayOfMonth(startDate), DateUtil.DATE_SHOW_FORMAT)+" 单位:元");
head0.add(buffer.toString());
list.add(head0);
return list;
}
@RequestMapping("tttt")
public void tttt(){
Date startDate = DateUtil.parse("201910", DateUtil.MONTHS_PATTERN);
Date endDate = DateUtil.plusMonths(startDate, 1);
Map map=new HashMap();
map.put("StartDate", startDate);
map.put("EndDate", endDate);
easyExcel.repeated(fileName,"s",getDateList(),map);
}
}
付个时间工具类
package com.easyexcel.demo.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
/**
*
* @author Kodak
* @version Id: DateUtil.java, v 0.1 2018/12/8 16:26 lai_kd Exp $$
*/
@Slf4j
public class DateUtil {
/**
* 日期格式:yyyyMM
*/
public static final String MONTHS_PATTERN = "yyyyMM";
/**
* 日期格式:MMdd
*/
public static final String MONTHS_AND_DAY = "MMdd";
/**
* 日期格式:yyMMdd
*/
public static final String SHOT_DATE_PATTERN = "yyMMdd";
/**
* 日期格式:yyyyMMdd
*/
public static final String DATE_PATTERN = "yyyyMMdd";
/**
* 日期格式:yyyyMMddHH
*/
public static final String HOUR_PATTERN = "yyyyMMddHH";
/**
* 日期格式:yyyyMMddHHmm
*/
public static final String MINUTE_PATTERN = "yyyyMMddHHmm";
/**
* 日期时间格式:yyyyMMddHHmmss
*/
public static final String FULL_PATTERN = "yyyyMMddHHmmss";
/**
* 日期时间格式:yyyyMMddHHmmss
*/
public static final String READ_PATTERN = "yyyyMMddHHmmssSSS";
/**
* 日期时间格式:yyyy-MM-dd
*/
public static final String DATE_SHOW_FORMAT = "yyyy-MM-dd";
/**
* 日期格式:yyyy-MM-dd HH:mm:ss
*/
public static final String STANDARD_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 日期格式:yyyy/MM/dd
*/
public static final String SLASH_PATTERN = "yyyy/MM/dd";
/**
* 获取当前日期
*
* @return 当前日期
*/
public static Date getCurrentDate() {
return DateTime.now().toDate();
}
/**
* 获取当前时间 格式: yyyyMMddHHmmss
*
* @return 字符日期 格式:yyyyMMddHHmmss
*/
public static String getCurrent() {
return getCurrent(FULL_PATTERN);
}
/**
* 获取当前时间 格式: 自定义
*
* @param pattern 时间格式
* @return 自定义格式的当前时间
*/
public static String getCurrent(String pattern) {
return DateTime.now().toString(pattern);
}
/**
* 将字符串转换成固定格式时间
*
* @param date 日期
* @param pattern 自定义格式
* @return 转换后日期
*/
public static Date parse(String date, String pattern) {
DateTime dateTime = parseTime(date, pattern);
if (dateTime == null) {
return null;
}
return dateTime.toDate();
}
/**
* 将字符串转换成固定格式时间
*
* @param date 日期
* @param pattern 自定义格式
* @return 转换后日期
*/
public static DateTime parseTime(String date, String pattern) {
return DateTimeFormat.forPattern(pattern).parseDateTime(date);
}
/**
* 将字符串转换成固定格式时间
*
* @param date 日期
* @param pattern 自定义格式
* @return 转换后日期
*/
public static Date parseStrToDate(String date, String pattern) {
if (StringUtils.isEmpty(date) || StringUtils.isEmpty(pattern) || date.length() != pattern.length()) {
return null;
}
//todo localdatetime
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date parse = null;
try {
parse = sdf.parse(date);
} catch (ParseException e) {
}
return parse;
}
/**
* Date类型转换String 格式:yyyyMMdd
*
* @param date 日期
* @return String类型
*/
public static String defaultFormat(Date date) {
if (date == null) {
return null;
}
return new DateTime(date).toString(DATE_PATTERN);
}
/**
* Date类型转换String 格式:自定义
*
* @param date 日期
* @param pattern 自定义格式
* @return String类型
*/
public static String format(Date date, String pattern) {
if (date == null) {
return null;
}
return new DateTime(date).toString(pattern);
}
/**
* 获取当前时间
*
* @return Date
*/
public static Date getCurrentDate(String pattern) {
DateTimeFormatter format = DateTimeFormat.forPattern(pattern);
return DateTime.parse(new DateTime().toString(pattern), format).toDate();
}
/**
* 根据 pattern 将 dateTime 时间进行格式化
* 用来去除时分秒,具体根据结果以 pattern 为准
*
* @param date payDate 时间
* @return payDate 时间
*/
public static Date formatToDate(Date date, String pattern) {
if (date == null) {
return null;
}
DateTimeFormatter format = DateTimeFormat.forPattern(pattern);
return DateTime.parse(new DateTime(date).toString(pattern), format).toDate();
}
/**
* 日期增减,负数为减
*
* @param dayNum 天数
* @return 时间
*/
public static Date plusDays(int dayNum) {
return new DateTime().plusDays(dayNum).toDate();
}
/**
* 日期增减,负数为减
*
* @param dayNum 天数
* @return 时间
*/
public static Date plusDays(Date date, int dayNum) {
return new DateTime(date).plusDays(dayNum).toDate();
}
/**
* 分钟增减,负数为减
*
* @param minutes 分钟数
* @return 时间
*/
public static Date plusMinutes(Date date, int minutes) {
return new DateTime(date).plusMinutes(minutes).toDate();
}
/**
* 月份增减,负数为减
*
* @param monthsNum 天数
* @return 时间
*/
public static Date plusMonths(Date date, int monthsNum) {
return new DateTime(date).plusMonths(monthsNum).toDate();
}
/**
* 增加时间
*
* @param date 时间
* @param calendarField 时间格式
* @param amount 间隔
* @return 日期
*/
public static Date addDate(Date date, int calendarField, int amount) {
if (date == null) {
throw new IllegalArgumentException("The date could not be null!");
}
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(calendarField, amount);
return c.getTime();
}
/**
* 按秒偏移,根据{@code source}得到{@code seconds}秒之后的日期<Br>
*
* @param source , 要求非空
* @param seconds , 秒数,可以为负
* @return 新创建的Date对象
*/
public static Date addSeconds(Date source, int seconds) {
return addDate(source, Calendar.SECOND, seconds);
}
/**
* 根据传入的时分秒毫秒获取固定的当日时间点
*
* @param hour 小时
* @param minute 分钟
* @param second 秒
* @param millisecond 毫秒
* @return 时间点
*/
public static Calendar getCurrentCalendar(int hour, int minute, int second, int millisecond) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, millisecond);
return calendar;
}
/**
* 根据传入的时分秒毫秒获取指定日期的时间点
*
* @param date 日期
* @param hour 小时
* @param minute 分钟
* @param second 秒
* @param millisecond 毫秒
* @return 时间点
*/
public static Calendar getDateCalendar(Date date, int hour, int minute, int second, int millisecond) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, millisecond);
return calendar;
}
/**
* 计算当月的最后一天
*
* @param date 日期
* @return 当月最后一天
*/
public static String getMonthEndDay(Date date) {
DateTime dateTime = getDateTime(date);
return String.valueOf(getDateTime(getMonthEnd(dateTime)).dayOfMonth().get());
}
/**
* 计算当月的第一天
*
* @param date 日期
* @return 当月最后一天
*/
public static Date getMonthBegDay(Date date) {
DateTime dateTime = getDateTime(date);
return dateTime.plusDays(1 - dateTime.getDayOfMonth()).toDate();
}
/**
* 计算当月的最后一天
*
* @param dateTime 日期
* @return 日期对象
*/
public static Date getMonthEnd(DateTime dateTime) {
return dateTime.plusMonths(1).plusDays(-dateTime.plusMonths(1).getDayOfMonth()).toDate();
}
/**
* 判断是否是每月的第一天
*
* @param dateTime 日期
* @return 日期对象
*/
public static boolean checkMonthFirstDate(DateTime dateTime) {
return 1 == dateTime.getDayOfMonth();
}
/**
* 获取DateTime日期对象
*
* @param date 日期
* @return DateTime对象
*/
public static DateTime getDateTime(Date date) {
return DateUtil.parseTime(DateUtil.format(date, DateUtil.DATE_PATTERN),
DateUtil.DATE_PATTERN);
}
/**
* 返回当月最后一天的日期
*
* @param date 日期
* @return 返回当月最后一天的日期
*/
public static Date getLastDayOfMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
return calendar.getTime();
}
/**
* 两个时间之间相差距离多少天
*
* @param date1 时间参数 1
* @param date2 时间参数 2
* @return 相差天数
*/
public static long getDistanceDays(Date date1, Date date2) {
long time1 = date1.getTime();
long time2 = date2.getTime();
long diff;
if (time1 < time2) {
diff = time2 - time1;
} else {
diff = time1 - time2;
}
return diff / (1000 * 60 * 60 * 24);
}
/**
* 两个时间间的差值
*
* @param date1 时间参数 1
* @param date2 时间参数 2
* @return 相差时间
*/
public static long getTimeDifference(Date date1, Date date2) {
long time1 = date1.getTime();
long time2 = date2.getTime();
return time1 - time2;
}
/**
* 获取当前是一周中的第几天
*
* @param date yyyyMMdd 或者 yyyy-MM-dd
* @return
* @throws ParseException
*/
public static String getDayOfWeek(String date) throws ParseException {
date = date.replaceAll("[-]", "");
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
cal.setTime(sdf.parse(date));
int week = cal.get(Calendar.DAY_OF_WEEK);
return String.valueOf((week == 1) ? 7 : week - 1);
}
/**
* 获取本月的最后一天
*
* @param date yyyyMMdd 或者 yyyy-MM-dd
* @return yyyyMMdd
* @throws ParseException
*/
public static String getLastDayOfMonth(String date) throws ParseException {
date = date.replaceAll("[-]", "");
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
cal.setTime(sdf.parse(date));
int day = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
cal.set(Calendar.DATE, day);
return sdf.format(cal.getTime());
}
/**
* 获取上个月的最后一天
*
* @param date yyyyMMdd 或者 yyyy-MM-dd
* @return yyyyMMdd
* @throws ParseException
*/
public static String getLastDayOfLastMonth(String date) throws ParseException {
date = date.replaceAll("[-]", "");
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
cal.setTime(sdf.parse(date));
cal.add(Calendar.MONTH, -1);
int day = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
cal.set(Calendar.DATE, day);
return sdf.format(cal.getTime());
}
/**
* date
* 判断传入参数格式为yyyyMMdd的数据是否是有效的日期类型
*
* @param inputDate
* @return
*/
public static boolean validDate(String inputDate) {
return inputDate.matches("[1-9][0-9]{3}(0[0-9]|1[0-2])(0[0-9]|1[0-9]|2[0-9]|3[0-1])");
}
/**
* 获取当前日距离年初(1月1日)的天数
*
* @param date
* @return
* @throws ParseException
*/
public static int getDayOfYear(String date) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Calendar c = Calendar.getInstance();
c.setTime(format.parse(date));
int days = c.get(Calendar.DAY_OF_YEAR);
return days - 1;
}
/**
* 判断当前时间,是否在传入时间到传入时间一小时后的时间段内
* @param startTime 传入时间格式为 HH:mm:ss
* @return boolean 返回值为true,当前时间在该时间后一小时内; 返回值为false,当前时间在
* @throws ParseException
*/
public static boolean isEffectiveDate(String startTime) throws ParseException {
//获取当前时间
SimpleDateFormat formater = new SimpleDateFormat("HH:mm:ss");
String currentTime = formater.format(new Date());
//传入的字符串时间转化为时间格式
long now = formater.parse(currentTime).getTime();
long start = formater.parse(startTime).getTime();
//传入时间后一小时
long end = start + (60*60*1000);
//判断时间是否值指定区间内
return now >= start && now <= end;
}
/**
* 将object转换成本地时间
* @param o 需要转换的时间 格式为: Mon Nov 11 15:19:15 CST 2019
* @return 返回 yyyy-MM-dd HH:mm:ss 格式数据
* @throws ParseException 异常
*/
public static String getObjToDate(Object o, String pattern) throws ParseException {
Date date=new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK).parse(String.valueOf(o));
//格式化
SimpleDateFormat sdf=new SimpleDateFormat(pattern);
String sDate=sdf.format(date);
return sDate;
}
}
就此结束。。。可直接测试
手机扫一扫
移动阅读更方便
你可能感兴趣的文章