开发手册 欢迎您!
软件开发者资料库

Java EasyExcel创建读写操作Excel(.xls,.xlsx)用法及示例代码

EasyExcel是阿里开源维护的,快速、简单避免OOM的Java处理Excel工具,Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。

通过Maven添加引用EasyExcel的Pom.xml,如下:


com.alibaba
easyexcel
1.0.1

1、读取Excel代码

package com.alibaba.easyexcel.test.demo.read;import java.io.File;import java.util.List;import java.util.Map;import org.junit.Ignore;import org.junit.Test;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.alibaba.easyexcel.test.util.TestFileUtil;import com.alibaba.excel.EasyExcel;import com.alibaba.excel.ExcelReader;import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.format.DateTimeFormat;import com.alibaba.excel.annotation.format.NumberFormat;import com.alibaba.excel.converters.DefaultConverterLoader;import com.alibaba.excel.read.metadata.ReadSheet;import com.alibaba.fastjson.JSON;/** * 读的常见写法 * * @author Jiaju Zhuang */@Ignorepublic class ReadTest {    private static final Logger LOGGER = LoggerFactory.getLogger(ReadTest.class);    /**     * 最简单的读     * 

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener} *

* 3. 直接读即可 */ @Test public void simpleRead() { // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 // 写法1: String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead(); // 写法2: fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; ExcelReader excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build(); ReadSheet readSheet = EasyExcel.readSheet(0).build(); excelReader.read(readSheet); // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的 excelReader.finish(); } /** * 指定列的下标或者列名 * *

* 1. 创建excel对应的实体对象,并使用{@link ExcelProperty}注解. 参照{@link IndexOrNameData} *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link IndexOrNameDataListener} *

* 3. 直接读即可 */ @Test public void indexOrNameRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里默认读取第一个sheet EasyExcel.read(fileName, IndexOrNameData.class, new IndexOrNameDataListener()).sheet().doRead(); } /** * 读多个或者全部sheet,这里注意一个sheet不能读取多次,多次读取需要重新读取文件 *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener} *

* 3. 直接读即可 */ @Test public void repeatedRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 读取全部sheet // 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写 EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).doReadAll(); // 读取部分sheet fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; ExcelReader excelReader = EasyExcel.read(fileName).build(); // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener ReadSheet readSheet1 = EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build(); ReadSheet readSheet2 = EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build(); // 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能 excelReader.read(readSheet1, readSheet2); // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的 excelReader.finish(); } /** * 日期、数字或者自定义格式转换 *

* 默认读的转换器{@link DefaultConverterLoader#loadDefaultReadConverter()} *

* 1. 创建excel对应的实体对象 参照{@link ConverterData}.里面可以使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解 *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link ConverterDataListener} *

* 3. 直接读即可 */ @Test public void converterRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet EasyExcel.read(fileName, ConverterData.class, new ConverterDataListener()) // 这里注意 我们也可以registerConverter来指定自定义转换器, 但是这个转换变成全局了, 所有java为string,excel为string的都会用这个转换器。 // 如果就想单个字段使用请使用@ExcelProperty 指定converter // .registerConverter(new CustomStringStringConverter()) // 读取sheet .sheet().doRead(); } /** * 多行头 * *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener} *

* 3. 设置headRowNumber参数,然后读。 这里要注意headRowNumber如果不指定, 会根据你传入的class的{@link ExcelProperty#value()}里面的表头的数量来决定行数, * 如果不传入class则默认为1.当然你指定了headRowNumber不管是否传入class都是以你传入的为准。 */ @Test public void complexHeaderRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet() // 这里可以设置1,因为头就是一行。如果多行头,可以设置其他值。不传入也可以,因为默认会根据DemoData 来解析,他没有指定头,也就是默认1行 .headRowNumber(1).doRead(); } /** * 读取表头数据 * *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoHeadDataListener} *

* 3. 直接读即可 */ @Test public void headerRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet EasyExcel.read(fileName, DemoData.class, new DemoHeadDataListener()).sheet().doRead(); } /** * 读取公式和单元格类型 * *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoHeadDataListener} *

* 3. 直接读即可 */ @Test public void cellDataRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "cellDataDemo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet EasyExcel.read(fileName, CellDataReadDemoData.class, new CellDataDemoHeadDataListener()).sheet().doRead(); } /** * 数据转换等异常处理 * *

* 1. 创建excel对应的实体对象 参照{@link ExceptionDemoData} *

* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoExceptionListener} *

* 3. 直接读即可 */ @Test public void exceptionRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet EasyExcel.read(fileName, ExceptionDemoData.class, new DemoExceptionListener()).sheet().doRead(); } /** * 同步的返回,不推荐使用,如果数据量大会把数据放到内存里面 */ @Test public void synchronousRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish List list = EasyExcel.read(fileName).head(DemoData.class).sheet().doReadSync(); for (DemoData data : list) { LOGGER.info("读取到数据:{}", JSON.toJSONString(data)); } // 这里 也可以不指定class,返回一个list,然后读取第一个sheet 同步读取会自动finish List> listMap = EasyExcel.read(fileName).sheet().doReadSync(); for (Map data : listMap) { // 返回每条数据的键值对 表示所在的列 和所在列的值 LOGGER.info("读取到数据:{}", JSON.toJSONString(data)); } } /** * 不创建对象的读,不是特别推荐使用,都用String接收对日期的支持不是很好 */ @Test public void noModleRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 只要,然后读取第一个sheet 同步读取会自动finish EasyExcel.read(fileName, new NoModleDataListener()).sheet().doRead(); }}

示例代码地址https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java

2、创建写Excel代码

package com.alibaba.easyexcel.test.demo.write;import java.io.File;import java.io.InputStream;import java.net.URL;import java.util.ArrayList;import java.util.Date;import java.util.HashSet;import java.util.List;import java.util.Set;import org.apache.poi.ss.usermodel.FillPatternType;import org.apache.poi.ss.usermodel.IndexedColors;import org.apache.poi.xssf.streaming.SXSSFSheet;import org.junit.Ignore;import org.junit.Test;import com.alibaba.easyexcel.test.util.TestFileUtil;import com.alibaba.excel.EasyExcel;import com.alibaba.excel.ExcelWriter;import com.alibaba.excel.annotation.ExcelProperty;import com.alibaba.excel.annotation.format.DateTimeFormat;import com.alibaba.excel.annotation.format.NumberFormat;import com.alibaba.excel.annotation.write.style.ColumnWidth;import com.alibaba.excel.annotation.write.style.ContentRowHeight;import com.alibaba.excel.annotation.write.style.HeadRowHeight;import com.alibaba.excel.util.FileUtils;import com.alibaba.excel.write.merge.LoopMergeStrategy;import com.alibaba.excel.write.metadata.WriteSheet;import com.alibaba.excel.write.metadata.WriteTable;import com.alibaba.excel.write.metadata.style.WriteCellStyle;import com.alibaba.excel.write.metadata.style.WriteFont;import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;/** * 写的常见写法 * * @author Jiaju Zhuang */@Ignorepublic class WriteTest {    /**     * 最简单的写     * 

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 直接写即可 */ @Test public void simpleWrite() { // 写法1 String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data()); // 写法2 fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写 ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet("模板").build(); excelWriter.write(data(), writeSheet); /// 千万别忘记finish 会帮忙关闭流 excelWriter.finish(); } /** * 根据参数只导出指定列 *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 根据自己或者排除自己需要的列 *

* 3. 直接写即可 */ @Test public void excludeOrIncludeWrite() { String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx"; // 根据用户传入字段 假设我们要忽略 date Set excludeColumnFiledNames = new HashSet(); excludeColumnFiledNames.add("date"); // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板") .doWrite(data()); fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx"; // 根据用户传入字段 假设我们只要导出 date Set includeColumnFiledNames = new HashSet(); includeColumnFiledNames.add("date"); // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板") .doWrite(data()); } /** * 指定写入的列 *

* 1. 创建excel对应的实体对象 参照{@link IndexData} *

* 2. 使用{@link ExcelProperty}注解指定写入的列 *

* 3. 直接写即可 */ @Test public void indexWrite() { String fileName = TestFileUtil.getPath() + "indexWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(data()); } /** * 复杂头写入 *

* 1. 创建excel对应的实体对象 参照{@link ComplexHeadData} *

* 2. 使用{@link ExcelProperty}注解指定复杂的头 *

* 3. 直接写即可 */ @Test public void complexHeadWrite() { String fileName = TestFileUtil.getPath() + "complexHeadWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data()); } /** * 重复多次写入 *

* 1. 创建excel对应的实体对象 参照{@link ComplexHeadData} *

* 2. 使用{@link ExcelProperty}注解指定复杂的头 *

* 3. 直接调用二次写入即可 */ @Test public void repeatedWrite() { // 方法1 如果写到同一个sheet String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写 ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build(); // 这里注意 如果同一个sheet只要创建一次 WriteSheet writeSheet = EasyExcel.writerSheet("模板").build(); // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来 for (int i = 0; i < 5; i++) { // 分页去数据库查询数据 这里可以去数据库查询每一页的数据 List data = data(); excelWriter.write(data, writeSheet); } /// 千万别忘记finish 会帮忙关闭流 excelWriter.finish(); // 方法2 如果写到不同的sheet 同一个对象 fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 指定文件 excelWriter = EasyExcel.write(fileName, DemoData.class).build(); // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面 for (int i = 0; i < 5; i++) { // 每次都要创建writeSheet 这里注意必须指定sheetNo writeSheet = EasyExcel.writerSheet(i, "模板").build(); // 分页去数据库查询数据 这里可以去数据库查询每一页的数据 List data = data(); excelWriter.write(data, writeSheet); } /// 千万别忘记finish 会帮忙关闭流 excelWriter.finish(); // 方法3 如果写到不同的sheet 不同的对象 fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 指定文件 excelWriter = EasyExcel.write(fileName).build(); // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面 for (int i = 0; i < 5; i++) { // 每次都要创建writeSheet 这里注意必须指定sheetNo。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变 writeSheet = EasyExcel.writerSheet(i, "模板").head(DemoData.class).build(); // 分页去数据库查询数据 这里可以去数据库查询每一页的数据 List data = data(); excelWriter.write(data, writeSheet); } /// 千万别忘记finish 会帮忙关闭流 excelWriter.finish(); } /** * 日期、数字或者自定义格式转换 *

* 1. 创建excel对应的实体对象 参照{@link ConverterData} *

* 2. 使用{@link ExcelProperty}配合使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解 *

* 3. 直接写即可 */ @Test public void converterWrite() { String fileName = TestFileUtil.getPath() + "converterWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data()); } /** * 图片导出 *

* 1. 创建excel对应的实体对象 参照{@link ImageData} *

* 2. 直接写即可 */ @Test public void imageWrite() throws Exception { String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx"; // 如果使用流 记得关闭 InputStream inputStream = null; try { List list = new ArrayList(); ImageData imageData = new ImageData(); list.add(imageData); String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg"; // 放入五种类型的图片 实际使用只要选一种即可 imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath))); imageData.setFile(new File(imagePath)); imageData.setString(imagePath); inputStream = FileUtils.openInputStream(new File(imagePath)); imageData.setInputStream(inputStream); imageData.setUrl(new URL( "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg")); EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list); } finally { if (inputStream != null) { inputStream.close(); } } } /** * 根据模板写入 *

* 1. 创建excel对应的实体对象 参照{@link IndexData} *

* 2. 使用{@link ExcelProperty}注解指定写入的列 *

* 3. 使用withTemplate 写取模板 *

* 4. 直接写即可 */ @Test public void templateWrite() { String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; String fileName = TestFileUtil.getPath() + "templateWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).withTemplate(templateFileName).sheet().doWrite(data()); } /** * 列宽、行高 *

* 1. 创建excel对应的实体对象 参照{@link WidthAndHeightData} *

* 2. 使用注解{@link ColumnWidth}、{@link HeadRowHeight}、{@link ContentRowHeight}指定宽度或高度 *

* 3. 直接写即可 */ @Test public void widthAndHeightWrite() { String fileName = TestFileUtil.getPath() + "widthAndHeightWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, WidthAndHeightData.class).sheet("模板").doWrite(data()); } /** * 自定义样式 *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 创建一个style策略 并注册 *

* 3. 直接写即可 */ @Test public void styleWrite() { String fileName = TestFileUtil.getPath() + "styleWrite" + System.currentTimeMillis() + ".xlsx"; // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 背景设置为红色 headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex()); WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short)20); headWriteCellStyle.setWriteFont(headWriteFont); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 背景绿色 contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 contentWriteFont.setFontHeightInPoints((short)20); contentWriteCellStyle.setWriteFont(contentWriteFont); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板") .doWrite(data()); } /** * 合并单元格 *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 创建一个merge策略 并注册 *

* 3. 直接写即可 */ @Test public void mergeWrite() { String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx"; // 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写 LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0); // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板").doWrite(data()); } /** * 使用table去写入 *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 然后写入table即可 */ @Test public void tableWrite() { String fileName = TestFileUtil.getPath() + "tableWrite" + System.currentTimeMillis() + ".xlsx"; // 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例 // 这里 需要指定写用哪个class去写 ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.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.TRUE).build(); WriteTable writeTable1 = EasyExcel.writerTable(1).needHead(Boolean.TRUE).build(); // 第一次写入会创建头 excelWriter.write(data(), writeSheet, writeTable0); // 第二次写如也会创建头,然后在第一次的后面写入数据 excelWriter.write(data(), writeSheet, writeTable1); /// 千万别忘记finish 会帮忙关闭流 excelWriter.finish(); } /** * 动态头,实时生成头写入 *

* 思路是这样子的,先创建List头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据 * *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 然后写入table即可 */ @Test public void dynamicHeadWrite() { String fileName = TestFileUtil.getPath() + "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx"; EasyExcel.write(fileName) // 这里放入动态头 .head(head()).sheet("模板") // 当然这里数据也可以用 List> 去传入 .doWrite(data()); } /** * 自动列宽(不太精确) *

* 这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照 * {@link LongestMatchColumnWidthStyleStrategy}重新实现. *

* poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。 * *

* 1. 创建excel对应的实体对象 参照{@link LongestMatchColumnWidthData} *

* 2. 注册策略{@link LongestMatchColumnWidthStyleStrategy} *

* 3. 直接写即可 */ @Test public void longestMatchColumnWidthWrite() { String fileName = TestFileUtil.getPath() + "longestMatchColumnWidthWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, LongestMatchColumnWidthData.class) .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("模板").doWrite(dataLong()); } /** * 下拉,超链接等自定义拦截器(上面几点都不符合但是要对单元格进行操作的参照这个) *

* demo这里实现2点。1. 对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel 2. 对第一列第一行和第二行的数据新增下拉框,显示 测试1 测试2 *

* 1. 创建excel对应的实体对象 参照{@link DemoData} *

* 2. 注册拦截器 {@link CustomCellWriteHandler} {@link CustomSheetWriteHandler} *

* 2. 直接写即可 */ @Test public void customHandlerWrite() { String fileName = TestFileUtil.getPath() + "customHandlerWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).registerWriteHandler(new CustomSheetWriteHandler()) .registerWriteHandler(new CustomCellWriteHandler()).sheet("模板").doWrite(data()); } /** * 不创建对象的写 */ @Test public void noModleWrite() { // 写法1 String fileName = TestFileUtil.getPath() + "noModleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList()); } private List dataLong() { List list = new ArrayList(); for (int i = 0; i < 10; i++) { LongestMatchColumnWidthData data = new LongestMatchColumnWidthData(); data.setString("测试很长的字符串测试很长的字符串测试很长的字符串" + i); data.setDate(new Date()); data.setDoubleData(1000000000000.0); list.add(data); } return list; } private List> head() { List> list = new ArrayList>(); List head0 = new ArrayList(); head0.add("字符串" + System.currentTimeMillis()); List head1 = new ArrayList(); head1.add("数字" + System.currentTimeMillis()); List head2 = new ArrayList(); head2.add("日期" + System.currentTimeMillis()); list.add(head0); list.add(head1); list.add(head2); return list; } private List> dataList() { List> list = new ArrayList>(); for (int i = 0; i < 10; i++) { List data = new ArrayList(); data.add("字符串" + i); data.add(new Date()); data.add(0.56); list.add(data); } return list; } private List data() { List list = new ArrayList(); for (int i = 0; i < 10; i++) { DemoData data = new DemoData(); data.setString("字符串" + i); data.setDate(new Date()); data.setDoubleData(0.56); list.add(data); } return list; }}

代码地址https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java

3、Web上传下载Excel

/**     * 文件下载(失败了会返回一个有部分数据的Excel)     * 

1. 创建excel对应的实体对象 参照{@link DownloadData} *

2. 设置返回的 参数 *

3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大 */ @GetMapping("download") public void download(HttpServletResponse response) throws IOException { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("测试", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data()); } /** * 文件上传 *

1. 创建excel对应的实体对象 参照{@link UploadData} *

2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link UploadDataListener} *

3. 直接读即可 */ @PostMapping("upload") @ResponseBody public String upload(MultipartFile file) throws IOException { EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead(); return "success"; }

官方文档https://alibaba-easyexcel.github.io/



2009-2024 Copyright Wonhero.Com All Rights Reserved
深圳幻海软件技术有限公司 版权所有