Java利用EasyExcel讀取寫入Excel詳情
EasyExcel介紹
EasyExcel是一個基于Java的、快速、簡潔、解決大文件內(nèi)存溢出的Excel處理工具。他能讓你在不用考慮性能、內(nèi)存的等因素的情況下,快速完成Excel的讀、寫等功能。
為什么使用EasyExcel?
Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個嚴(yán)重的問題就是非常的耗內(nèi)存,poi有一套SAX模式的API可以一定程度的解決一些內(nèi)存溢出的問題,但POI還是有一些缺陷,比如07版Excel解壓縮以及解壓后存儲都是在內(nèi)存中完成的,內(nèi)存消耗依然很大。easyexcel重寫了poi對07版Excel的解析,一個3M的excel用POI sax解析依然需要100M左右內(nèi)存,改用easyexcel可以降低到幾M,并且再大的excel也不會出現(xiàn)內(nèi)存溢出;03版依賴POI的sax模式,在上層做了模型轉(zhuǎn)換的封裝,讓使用者更加簡單方便。
封裝使用
引入EasyExcel依賴
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>Excel文檔的自動列寬設(shè)置
public class CustomColumnWidthHandler extends AbstractColumnWidthStyleStrategy {
private static final int MAX_COLUMN_WIDTH = 255;
private static final int PADDING_WIDTH = 6;
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer integer, Boolean isHead) {
if (isHead) {
int columnWidth = cell.getStringCellValue().length() * 2 + PADDING_WIDTH;
columnWidth = Math.min(columnWidth, MAX_COLUMN_WIDTH);
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
}
}
}消費(fèi)監(jiān)聽器:
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class EasyExcelConsumerListener<T> extends AnalysisEventListener<T> {
private int pageSize;
private List<T> list;
private Consumer<List<T>> consumer;
public EasyExcelConsumerListener(int pageSize, Consumer<List<T>> consumer) {
this.pageSize = pageSize;
this.consumer = consumer;
list = new ArrayList<>(pageSize);
}
@Override
public void invoke(T data, AnalysisContext context) {
list.add(data);
if (list.size() >= pageSize) {
consumer.accept(list);
list.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
consumer.accept(list);
}
@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {
exception.printStackTrace();
throw exception;
}
}ExcelSheet
public class ExcelSheet<T> {
private String sheetName;
private T clazz;
private List<T> data;
public ExcelSheet() {
}
public ExcelSheet(String sheetName, T clazz, List<T> data) {
this.sheetName = sheetName;
this.clazz = clazz;
this.data = data;
}
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public T getClazz() {
return clazz;
}
public void setClazz(T clazz) {
this.clazz = clazz;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
@Override
public String toString() {
return "CreateExcelSheet{" +
"sheetName='" + sheetName + '\'' +
", clazz=" + clazz +
", data=" + data +
'}';
}
}LocalDateConverter
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.WriteCellData;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class LocalDateConverter implements Converter<LocalDate> {
@Override
public Class<LocalDate> supportJavaTypeKey() {
return LocalDate.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalDate convertToJavaData(ReadConverterContext<?> context) {
Calendar calendar = new GregorianCalendar(1900, 0, -1);
Date gregorianDate = calendar.getTime();
return LocalDate.parse((new SimpleDateFormat("yyyy-MM-dd")).format(
addDay(gregorianDate, context.getReadCellData().getNumberValue().intValue())),
DateTimeFormatter.ofPattern("yyyy-MM-dd")
);
}
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<LocalDate> context) {
return new WriteCellData<>(context.getValue().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
public static Date addDay(Date date, int day) {
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.add(5, day);
date = calendar.getTime();
return date;
}
}LocalDateTimeConverter
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.WriteCellData;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeConverter implements Converter<LocalDateTime> {
@Override
public Class<LocalDateTime> supportJavaTypeKey() {
return LocalDateTime.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalDateTime convertToJavaData(ReadConverterContext<?> context) {
return LocalDateTime.parse(context.getReadCellData().getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<LocalDateTime> context) {
return new WriteCellData<>(context.getValue().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}ByteArrayConverter
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.WriteCellData;
import java.nio.charset.StandardCharsets;
public class ByteArrayConverter implements Converter<byte[]> {
public ByteArrayConverter() {
}
@Override
public Class<byte[]> supportJavaTypeKey() {
return byte[].class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public byte[] convertToJavaData(ReadConverterContext<?> context) {
String stringValue = context.getReadCellData().getStringValue();
return stringValue.getBytes(StandardCharsets.UTF_8);
}
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<byte[]> context) {
return new WriteCellData((byte[])context.getValue());
}
}EasyExcel工具類
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class ExcelUtil extends EasyExcel {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtil.class);
private ExcelUtil() {}
/**
* 分批讀取
*/
public static <T> ExcelReaderBuilder read(String pathName, Class<T> head, Integer pageSize, Consumer<List<T>> consumer) {
return read(pathName, head, new EasyExcelConsumerListener<>(pageSize, consumer));
}
/**
* 分批讀取
*/
public static <T> ExcelReaderBuilder read(File file, Class<T> head, Integer pageSize, Consumer<List<T>> consumer) {
return read(file, head, new EasyExcelConsumerListener<>(pageSize, consumer));
}
/**
* 分批讀取
*/
public static <T> ExcelReaderBuilder read(InputStream inputStream, Class<T> head, Integer pageSize, Consumer<List<T>> consumer) {
return read(inputStream, head, new EasyExcelConsumerListener<>(pageSize, consumer));
}
/**
* 根據(jù)實(shí)體生成Excel模版(用于數(shù)據(jù)導(dǎo)入的模版下載)
*/
public static ExcelWriterBuilder write(String pathName, Class head) {
return EasyExcel.write(pathName, head)
.excelType(ExcelTypeEnum.XLSX)
.registerWriteHandler(buildCellStyle())
.registerWriteHandler(new CustomColumnWidthHandler());
}
/**
* 寫入
*/
public static void write(HttpServletResponse response, List<?> data, String fileName, String sheetName, Class clazz) throws Exception {
EasyExcel.write(getOutputStream(fileName, response), clazz)
.excelType(ExcelTypeEnum.XLSX)
.sheet(sheetName)
.registerWriteHandler(buildCellStyle())
.registerWriteHandler(new CustomColumnWidthHandler())
.doWrite(data);
}
/**
* 寫入
*/
public static void write(OutputStream outputStream, List<?> data, String sheetName, Class clazz) {
EasyExcel.write(outputStream, clazz)
.excelType(ExcelTypeEnum.XLSX)
.sheet(sheetName)
.registerWriteHandler(buildCellStyle())
.registerWriteHandler(new CustomColumnWidthHandler())
.doWrite(data);
}
private static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
return response.getOutputStream();
}
/**
* 獲取表頭
*/
public static Map<String, String> getHeadMap(Class<?> aClass) {
Map<String, String> HeadMap = new LinkedHashMap<>();
Field[] declaredFields = aClass.getDeclaredFields();
ExcelProperty excelProperty;
for (Field field : declaredFields) {
if (field != null) {
field.setAccessible(true);
if (field.isAnnotationPresent(ExcelProperty.class)) {
excelProperty = field.getAnnotation(ExcelProperty.class);
HeadMap.put(field.getName(), StringUtils.join(Arrays.asList(excelProperty.value()), ","));
}
}
}
return HeadMap;
}
/**
* 生成通用表格樣式
*/
public static HorizontalCellStyleStrategy buildCellStyle(){
//表頭樣式
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
headWriteCellStyle.setFillForegroundColor(IndexedColors.TEAL.getIndex());
headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
WriteFont font = new WriteFont();
font.setFontName("Microsoft YaHei Light");
font.setColor(IndexedColors.WHITE.getIndex());
font.setFontHeightInPoints((short) 11);
headWriteCellStyle.setWriteFont(font);
//內(nèi)容樣式
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}
/**
* 創(chuàng)建一個Excel文件多個Sheet
* @param sheetList
*/
public static void createExcel(List<ExcelSheet> sheetList, OutputStream os){
ExcelWriter excelWriter = null;
WriteSheet writeSheet = null;
int count = 0;
try {
excelWriter = EasyExcel.write(os)
.registerWriteHandler(buildCellStyle())
.registerWriteHandler(new CustomColumnWidthHandler())
.build();
for (ExcelSheet sheet : sheetList) {
writeSheet = EasyExcel.writerSheet(count++, sheet.getSheetName()).head((Class) sheet.getClazz()).build();
excelWriter.write(sheet.getData(),writeSheet);
}
} catch (Exception e) {
LOGGER.error("創(chuàng)建一個Excel文件多個Sheet失敗", e);
}finally {
if (null != excelWriter){
excelWriter.finish();
}
}
}
}例子
UserVo實(shí)體
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDate;
@Data
public class UserVo {
@ExcelProperty(value = "姓名")
private String name;
@ExcelProperty(value = "年齡")
private int age;
@ExcelProperty(value = "出生日期", converter = LocalDateConverter.class)
private LocalDate birthdate;
}導(dǎo)出用戶信息
ExcelUtil.write(httpServletResponse, list, "用戶信息.xlsx", "用戶信息", UserVo.class);
讀取用戶信息
ExcelUtil.read(filePath, UserVo.class, 1000, pageList -> {
pageList.forEach(user -> {
// 業(yè)務(wù)邏輯
});
}).sheet().doRead();到此這篇關(guān)于Java利用EasyExcel讀取寫入Excel詳情的文章就介紹到這了,更多相關(guān)Java 讀取Excel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring集成webSocket頁面訪問404問題的解決方法
這篇文章主要介紹了Spring集成webSocket頁面訪問404問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
解決報錯:java.lang.IllegalStateException: Failed to&nb
在項(xiàng)目開發(fā)中,可能會遇到Elasticsearch啟動報錯的問題,原因可能包括版本不一致、端口配置錯誤、配置文件不匹配及服務(wù)未啟動等,解決方法包括檢查進(jìn)程、重啟服務(wù)等,這些經(jīng)驗(yàn)可以幫助開發(fā)者快速定位問題并解決,保證項(xiàng)目順利運(yùn)行2024-10-10
Java線程池隊(duì)列PriorityBlockingQueue和SynchronousQueue詳解
這篇文章主要為大家介紹了Java線程池隊(duì)列PriorityBlockingQueue和SynchronousQueue詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
解決SpringBoot 測試類無法自動注入@Autowired的問題
這篇文章主要介紹了解決SpringBoot 測試類無法自動注入@Autowired的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
基于application和bootstrap的加載順序及區(qū)別說明
這篇文章主要介紹了application和bootstrap的加載順序及區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07

