Java利用EasyExcel讀取寫入Excel詳情
EasyExcel介紹
EasyExcel是一個(gè)基于Java的、快速、簡(jiǎn)潔、解決大文件內(nèi)存溢出的Excel處理工具。他能讓你在不用考慮性能、內(nèi)存的等因素的情況下,快速完成Excel的讀、寫等功能。
為什么使用EasyExcel?
Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個(gè)嚴(yán)重的問題就是非常的耗內(nèi)存,poi有一套SAX模式的API可以一定程度的解決一些內(nèi)存溢出的問題,但POI還是有一些缺陷,比如07版Excel解壓縮以及解壓后存儲(chǔ)都是在內(nèi)存中完成的,內(nèi)存消耗依然很大。easyexcel重寫了poi對(duì)07版Excel的解析,一個(gè)3M的excel用POI sax解析依然需要100M左右內(nèi)存,改用easyexcel可以降低到幾M,并且再大的excel也不會(huì)出現(xiàn)內(nèi)存溢出;03版依賴POI的sax模式,在上層做了模型轉(zhuǎn)換的封裝,讓使用者更加簡(jiǎn)單方便。
封裝使用
引入EasyExcel依賴
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency>
Excel文檔的自動(dòng)列寬設(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)建一個(gè)Excel文件多個(gè)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)建一個(gè)Excel文件多個(gè)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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring集成webSocket頁面訪問404問題的解決方法
這篇文章主要介紹了Spring集成webSocket頁面訪問404問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12解決報(bào)錯(cuò):java.lang.IllegalStateException: Failed to&nb
在項(xiàng)目開發(fā)中,可能會(huì)遇到Elasticsearch啟動(dòng)報(bào)錯(cuò)的問題,原因可能包括版本不一致、端口配置錯(cuò)誤、配置文件不匹配及服務(wù)未啟動(dòng)等,解決方法包括檢查進(jìn)程、重啟服務(wù)等,這些經(jīng)驗(yàn)可以幫助開發(fā)者快速定位問題并解決,保證項(xiàng)目順利運(yùn)行2024-10-10Java線程池隊(duì)列PriorityBlockingQueue和SynchronousQueue詳解
這篇文章主要為大家介紹了Java線程池隊(duì)列PriorityBlockingQueue和SynchronousQueue詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12解決SpringBoot 測(cè)試類無法自動(dòng)注入@Autowired的問題
這篇文章主要介紹了解決SpringBoot 測(cè)試類無法自動(dòng)注入@Autowired的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03基于application和bootstrap的加載順序及區(qū)別說明
這篇文章主要介紹了application和bootstrap的加載順序及區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07