当前位置: 首页 > news >正文

网站首页自动下拉广告闽侯县住房和城乡建设局网站

网站首页自动下拉广告,闽侯县住房和城乡建设局网站,厦门网站建设哪家强,上海软件开发企业一、什么是EasyExcel?二、对比ApachePoi 其他Excel框架 优势在于哪里三、本质上对于原生做了哪些优化#xff1f;四、有哪些功能五、如何实践#xff1f; 5.1 常规文件读取5.2 常规文件写入5.3 常规WEB的上传和下载 一、什么是EasyExcel? EasyExcel是对07版POI的提升和优…一、什么是EasyExcel?二、对比ApachePoi 其他Excel框架 优势在于哪里三、本质上对于原生做了哪些优化四、有哪些功能五、如何实践 5.1 常规文件读取5.2 常规文件写入5.3 常规WEB的上传和下载 一、什么是EasyExcel? EasyExcel是对07版POI的提升和优化能够有效解决内存占用大的问题将内存处理部分转移到磁盘。 从功能上就是poi 07版本能做的它都能做并且效率更高门槛更低。 在互联网平台上获得广泛使用在github上面star已经达到26700可见人气之旺。 二、对比ApachePoi 其他Excel框架 优势在于哪里 内存优化 EasyExcel出现的原因主要是为了优化内存的占用官方提供的数据就能够了解到 — 16M内存23秒读取75M的Excel, 这个Excel包含46W行25列。对于极速模式也会牺牲内存换取更快的速度要看取舍了。 读写行数 针对Excel03版本只能读取小于65535行。从Excel07版本开始读写行数都能够超过65535行但是由于框架性质的原因读取数据越多占用的内存就会增长迅速。速度也是较慢。 jar引用 对于POI这种通常都要引入几个相关的jar包jar包多了内部的版本就会和别的组件的依赖会出现更多冲突的可能。easyexcel目前只有一个jar。 三、本质上对于原生做了哪些优化 以上都是描述了EasyExcel从内存的角度,对于解析Exccel07版本做了优化具体的点有哪些呢待完善 四、有哪些功能 简单读模板读注解表头读注解自定义读处理器自定义读模板读无对象读固定多层表头读自定义多层表头读超链接、标注读图片读写也都有类似的写功能写入有自适应列宽的实现 有大量Handler可扩展非常灵活 五、如何实践 简单使用官方教程的测试用例来跟着代码一起了解功能。对于测试样例和文档都挺完备的非常好理解。 简单操作也可以直接移步官网https://easyexcel.opensource.alibaba.com/docs/current/ 5.1 常规文件读取 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.context.AnalysisContext; import com.alibaba.excel.converters.DefaultConverterLoader; import com.alibaba.excel.enums.CellExtraTypeEnum; import com.alibaba.excel.read.listener.PageReadListener; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.util.ListUtils; import com.alibaba.fastjson2.JSON; import com.learning.easyexcel.common.CellDataUser; import com.learning.easyexcel.common.User; import com.learning.easyexcel.common.UserExtra; import com.learning.easyexcel.common.UserFormat; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.Lists;import java.util.List; import java.util.Map;/*** 功能简述* 〈读取测试〉** author claire* date 2023/2/20 - 11:40 上午* since 1.0.0*/ Slf4j public class ReadTest {/*** 最简单的读* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link }* p* 3. 直接读即可*/public void simpleRead1() {// 写法1JDK8 ,不用额外写一个DemoDataListener// since: 3.0.0-beta1String fileName demo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheet 文件流会自动关闭// 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行// 具体需要返回多少行可以在PageReadListener的构造函数设置EasyExcel.read(fileName, User.class, new PageReadListenerUser(dataList - {for (User user : dataList) {log.info(读取到一条数据{}, JSON.toJSONString(user));}})).sheet().doRead();}public void simpleRead2() {// 写法2// 匿名内部类 不用额外写一个DemoDataListenerString fileName demo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, User.class, new ReadListenerUser() {/*** 单次缓存的数据量*/public static final int BATCH_COUNT 100;/*** 临时存储*/private ListUser cachedDataList ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);Overridepublic void invoke(User data, AnalysisContext context) {cachedDataList.add(data);if (cachedDataList.size() BATCH_COUNT) {saveData();// 存储完成清理 listcachedDataList Lists.newArrayList();}}Overridepublic void doAfterAllAnalysed(AnalysisContext context) {saveData();}/*** 加上存储数据库*/private void saveData() {log.info({}条数据开始存储数据库, cachedDataList.size());log.info(存储数据库成功);}}).sheet().doRead();}public void simpleRead3() {// 有个很重要的点 DemoDataListener 不能被spring管理要每次读取excel都要new,然后里面用到spring可以构造方法传进去// 写法3String fileName demo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, User.class, new UserDataListener()).sheet().doRead();}public void simpleRead4() {// 写法4String fileName demo.xlsx;// 一个文件一个readertry (ExcelReader excelReader EasyExcel.read(fileName, User.class, new UserDataListener()).build()) {// 构建一个sheet 这里可以指定名字或者noReadSheet readSheet EasyExcel.readSheet(0).build();// 读取一个sheetexcelReader.read(readSheet);}}/*** 指定列的下标或者列名** p* 1. 创建excel对应的实体对象,并使用{link ExcelProperty}注解. 参照{link }* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link }* p* 3. 直接读即可*/public void indexOrNameRead() {String fileName demo.xlsx;// 这里默认读取第一个sheetEasyExcel.read(fileName, User.class, new UserWithAnnoDataListener()).sheet().doRead();}/*** 读多个或者全部sheet,这里注意一个sheet不能读取多次多次读取需要重新读取文件* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link UserDataListener}* p* 3. 直接读即可*/public void multiSheetRead(){String fileName demo.xlsx;// 读取全部sheet// 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写EasyExcel.read(fileName, User.class, new UserDataListener()).doReadAll();// 读取部分sheetfileName demo.xlsx;// 写法1try (ExcelReader excelReader EasyExcel.read(fileName).build()) {// 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的ListenerReadSheet readSheet1 EasyExcel.readSheet(0).head(User.class).registerReadListener(new UserDataListener()).build();ReadSheet readSheet2 EasyExcel.readSheet(1).head(User.class).registerReadListener(new UserDataListener()).build();// 这里注意 一定要把sheet1 sheet2 一起传进去不然有个问题就是03版的excel 会读取多次浪费性能excelReader.read(readSheet1, readSheet2);}}/*** 日期、数字或者自定义格式转换* p* 默认读的转换器{link DefaultConverterLoader#loadDefaultReadConverter()}* p* 1. 创建excel对应的实体对象 参照{link UserFormat}.里面可以使用注解{link DateTimeFormat}、{link NumberFormat}或者自定义注解* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link }* p* 3. 直接读即可*/public void contentFormatWithAnnoRead(){String fileName demo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheetEasyExcel.read(fileName, UserFormat.class, new UserFormatDataListener())// 这里注意 我们也可以registerConverter来指定自定义转换器 但是这个转换变成全局了 所有java为string,excel为string的都会用这个转换器。// 如果就想单个字段使用请使用ExcelProperty 指定converter// .registerConverter(new CustomStringStringConverter())// 读取sheet.sheet().doRead();}/*** 多行头** p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link UserDataListener}* p* 3. 设置headRowNumber参数然后读。 这里要注意headRowNumber如果不指定 会根据你传入的class的{link ExcelProperty#value()}里面的表头的数量来决定行数* 如果不传入class则默认为1.当然你指定了headRowNumber不管是否传入class都是以你传入的为准。*/public void groupHeaderRead(){String fileName demo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheetEasyExcel.read(fileName, User.class, new UserDataListener()).sheet()// 这里可以设置1因为头就是一行。如果多行头可以设置其他值。不传入也可以因为默认会根据DemoData 来解析他没有指定头也就是默认1行.headRowNumber(3).doRead();}/*** 读取表头数据** p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link UserDataListener}* p* 3. 直接读即可*/public void headerRead() {String fileName demo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheetEasyExcel.read(fileName, User.class, new UserDataListener()).sheet().doRead();}/*** 额外信息批注、超链接、合并单元格信息读取* p* 由于是流式读取没法在读取到单元格数据的时候直接读取到额外信息所以只能最后通知哪些单元格有哪些额外信息** p* 1. 创建excel对应的实体对象 参照{link UserExtra}* p* 2. 由于默认异步读取excel所以需要创建excel一行一行的回调监听器参照{link UserExtraListener}* p* 3. 直接读即可** since 2.2.0-beat1*/public void extraRead() {String fileName extra.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheetEasyExcel.read(fileName, UserExtra.class, new UserExtraListener())// 需要读取批注 默认不读取.extraRead(CellExtraTypeEnum.COMMENT)// 需要读取超链接 默认不读取.extraRead(CellExtraTypeEnum.HYPERLINK)// 需要读取合并单元格信息 默认不读取.extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();}/*** 读取公式和单元格类型** p* 1. 创建excel对应的实体对象 参照{link CellDataUser}* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link CellDataUserHeadListener}* p* 3. 直接读即可** since 2.2.0-beat1*/public void cellDataRead() {String fileName cellDataDemo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheetEasyExcel.read(fileName, CellDataUser.class, new CellDataUserHeadListener()).sheet().doRead();}/*** 数据转换等异常处理** p* 1. 创建excel对应的实体对象 参照{link }* p* 2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link }* p* 3. 直接读即可*/public void exceptionConvertRead(){//遇到异常转换为有含义的数据在listen中转换 // Override // public void onException(Exception exception, AnalysisContext context) { // log.error(解析失败但是继续解析下一行:{}, exception.getMessage()); // // 如果是某一个单元格的转换异常 能获取到具体行号 // // 如果要获取头的信息 配合invokeHeadMap使用 // if (exception instanceof ExcelDataConvertException) { // ExcelDataConvertException excelDataConvertException (ExcelDataConvertException)exception; // log.error(第{}行第{}列解析异常数据为:{}, excelDataConvertException.getRowIndex(), // excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData()); // } // }}/*** 同步的返回不推荐使用如果数据量大会把数据放到内存里面*/public void synchronousRead() {String fileName demo.xlsx;// 这里 需要指定读用哪个class去读然后读取第一个sheet 同步读取会自动finishListUser list EasyExcel.read(fileName).head(User.class).sheet().doReadSync();for (User data : list) {log.info(读取到数据:{}, JSON.toJSONString(data));}// 这里 也可以不指定class返回一个list然后读取第一个sheet 同步读取会自动finishListMapInteger, String listMap EasyExcel.read(fileName).sheet().doReadSync();for (MapInteger, String data : listMap) {// 返回每条数据的键值对 表示所在的列 和所在列的值log.info(读取到数据:{}, JSON.toJSONString(data));}}/*** 不创建对象的读逻辑里面入DB或入缓存用MAP来承载数据*/public void noModelRead() {String fileName demo.xlsx;// 这里 只要然后读取第一个sheet 同步读取会自动finish // EasyExcel.read(fileName, new NoModelDataListener()).sheet().doRead();}} 5.2 常规文件写入 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.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.data.*; import com.alibaba.excel.util.BooleanUtils; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.ListUtils; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; 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; import com.learning.easyexcel.LongestMatchColumnWidthData; import com.learning.easyexcel.common.*; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.streaming.SXSSFSheet;import java.io.File; import java.io.InputStream; import java.net.URL; import java.util.*;/*** 功能简述* 〈x写Excel〉** author claire* date 2023/2/20 - 2:53 下午* since 1.0.0*/ public class WriteTest {/*** 最简单的写* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 直接写即可*/public void simpleWrite1() {// 注意 simpleWrite在数据量不大的情况下可以使用5000以内具体也要看实际情况数据量大参照 重复多次写入// 写法1 JDK8// since: 3.0.0-beta1String fileName simpleWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, User.class).sheet(模板).doWrite(() - {// 分页查询数据return data();});}public void simpleWrite2() {// 写法2String fileName simpleWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, User.class).sheet(模板).doWrite(data());}public void simpleWrite3() {// 写法3String fileName simpleWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写try (ExcelWriter excelWriter EasyExcel.write(fileName, User.class).build()) {WriteSheet writeSheet EasyExcel.writerSheet(模板).build();excelWriter.write(data(), writeSheet);}}/*** 根据参数只导出指定列* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 根据自己或者排除自己需要的列* p* 3. 直接写即可** since 2.1.1*/public void excludeOrIncludeWrite() {String fileName excludeOrIncludeWrite System.currentTimeMillis() .xlsx;// 这里需要注意 在使用ExcelProperty注解的使用如果想不空列则需要加入order字段而不是index,order会忽略空列然后继续往后而index不会忽略空列在第几列就是第几列。// 根据用户传入字段 假设我们要忽略 scoreSetString excludeColumnFieldNames new HashSet();excludeColumnFieldNames.add(score);// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, User.class).excludeColumnFieldNames(excludeColumnFieldNames).sheet(模板).doWrite(data());fileName excludeOrIncludeWrite System.currentTimeMillis() .xlsx;// 根据用户传入字段 假设我们只要导出 scoreSetString includeColumnFieldNames new HashSet();includeColumnFieldNames.add(score);// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, User.class).includeColumnFieldNames(includeColumnFieldNames).sheet(模板).doWrite(data());}/*** 指定写入的列* p* 1. 创建excel对应的实体对象 参照{link UserWriteFormat}* p* 2. 使用{link ExcelProperty}注解指定写入的列* p* 3. 直接写即可*/public void indexWrite() {String fileName indexWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, UserWriteFormat.class).sheet(模板).doWrite(data());}/*** 复杂头写入这个很实用快速导出不用纠结于表头的设计* p* 1. 创建excel对应的实体对象 参照{link ComplexHeadData}* p* 2. 使用{link ExcelProperty}注解指定复杂的头* p* 3. 直接写即可*/public void complexHeadWrite() {String fileName complexHeadWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, ComplexHeadData.class).sheet(模板).doWrite(data());}/*** 重复多次写入* p* 1. 创建excel对应的实体对象 参照{link ComplexHeadData}* p* 2. 使用{link ExcelProperty}注解指定复杂的头* p* 3. 直接调用二次写入即可*/public void repeatedWrite1() {// 方法1: 如果写到同一个sheetString fileName repeatedWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写try (ExcelWriter excelWriter EasyExcel.write(fileName, User.class).build()) {// 这里注意 如果同一个sheet只要创建一次WriteSheet writeSheet EasyExcel.writerSheet(模板).build();// 去调用写入,这里我调用了五次实际使用时根据数据库分页的总的页数来for (int i 0; i 5; i) {// 分页去数据库查询数据 这里可以去数据库查询每一页的数据ListUser data data();excelWriter.write(data, writeSheet);}}}public void repeatedWrite2() {// 方法2: 如果写到不同的sheet 同一个对象String fileName repeatedWrite System.currentTimeMillis() .xlsx;// 这里 指定文件try (ExcelWriter excelWriter EasyExcel.write(fileName, User.class).build()) {// 去调用写入,这里我调用了五次实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i 0; i 5; i) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样WriteSheet writeSheet EasyExcel.writerSheet(i, 模板 i).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据ListUser data data();excelWriter.write(data, writeSheet);}}}public void repeatedWrite3() {// 方法3 如果写到不同的sheet 不同的对象String fileName repeatedWrite System.currentTimeMillis() .xlsx;// 这里 指定文件try (ExcelWriter excelWriter EasyExcel.write(fileName).build()) {// 去调用写入,这里我调用了五次实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面for (int i 0; i 5; i) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变我这里为了方便 所以用的同一个class// 实际上可以一直变WriteSheet writeSheet EasyExcel.writerSheet(i, 模板 i).head(User.class).build();// 分页去数据库查询数据 这里可以去数据库查询每一页的数据ListUser data data();excelWriter.write(data, writeSheet);}}}/*** 日期、数字或者自定义格式转换这个是常见的指定格式导出Excel自定义的convert可以做一些枚举转换、字段拆分等* p* 1. 创建excel对应的实体对象 参照{link UserFormat}* p* 2. 使用{link ExcelProperty}配合使用注解{link DateTimeFormat}、{link NumberFormat}或者自定义注解* p* 3. 直接写即可*/public void converterWrite() {String fileName converterWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, UserFormat.class).sheet(模板).doWrite(data());}/*** 图片导出* p* 1. 创建excel对应的实体对象 参照{link ImageDemoData}* p* 2. 直接写即可*/public void imageWrite() throws Exception {String fileName imageWrite System.currentTimeMillis() .xlsx;// 这里注意下 所有的图片都会放到内存 暂时没有很好的解法大量图片的情况下建议 2选1:// 1. 将图片上传到oss 或者其他存储网站: https://www.aliyun.com/product/oss 然后直接放链接// 2. 使用: https://github.com/coobird/thumbnailator 或者其他工具压缩图片String imagePath converter File.separator img.jpg;try (InputStream inputStream FileUtils.openInputStream(new File(imagePath))) {ListImageDemoData list ListUtils.newArrayList();ImageDemoData imageDemoData new ImageDemoData();list.add(imageDemoData);// 放入五种类型的图片 实际使用只要选一种即可imageDemoData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));imageDemoData.setFile(new File(imagePath));imageDemoData.setString(imagePath);imageDemoData.setInputStream(inputStream);imageDemoData.setUrl(new URL(https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg));// 这里演示// 需要额外放入文字// 而且需要放入2个图片// 第一个图片靠左// 第二个靠右 而且要额外的占用他后面的单元格WriteCellDataVoid writeCellData new WriteCellData();imageDemoData.setWriteCellDataFile(writeCellData);// 这里可以设置为 EMPTY 则代表不需要其他数据了writeCellData.setType(CellDataTypeEnum.STRING);writeCellData.setStringValue(额外的放一些文字);// 可以放入多个图片ListImageData imageDataList new ArrayList();ImageData imageData new ImageData();imageDataList.add(imageData);writeCellData.setImageDataList(imageDataList);// 放入2进制图片imageData.setImage(FileUtils.readFileToByteArray(new File(imagePath)));// 图片类型imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);// 上 右 下 左 需要留空// 这个类似于 css 的 margin// 这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。imageData.setTop(5);imageData.setRight(40);imageData.setBottom(5);imageData.setLeft(5);// 放入第二个图片imageData new ImageData();imageDataList.add(imageData);writeCellData.setImageDataList(imageDataList);imageData.setImage(FileUtils.readFileToByteArray(new File(imagePath)));imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);imageData.setTop(5);imageData.setRight(5);imageData.setBottom(5);imageData.setLeft(50);// 设置图片的位置 假设 现在目标 是 覆盖 当前单元格 和当前单元格右边的单元格// 起点相对于当前单元格为0 当然可以不写imageData.setRelativeFirstRowIndex(0);imageData.setRelativeFirstColumnIndex(0);imageData.setRelativeLastRowIndex(0);// 前面3个可以不写 下面这个需要写 也就是 结尾 需要相对当前单元格 往右移动一格// 也就是说 这个图片会覆盖当前单元格和 后面的那一格imageData.setRelativeLastColumnIndex(1);// 写入数据EasyExcel.write(fileName, ImageDemoData.class).sheet().doWrite(list);}}/*** 超链接、备注、公式、指定单个单元格的样式、单个单元格多种样式* p* 1. 创建excel对应的实体对象 参照{link WriteCellDemoData}* p* 2. 直接写即可** since 3.0.0-beta1*/public void writeCellDataWrite() {String fileName writeCellDataWrite System.currentTimeMillis() .xlsx;WriteCellDemoData writeCellDemoData new WriteCellDemoData();// 设置超链接WriteCellDataString hyperlink new WriteCellData(官方网站);writeCellDemoData.setHyperlink(hyperlink);HyperlinkData hyperlinkData new HyperlinkData();hyperlink.setHyperlinkData(hyperlinkData);hyperlinkData.setAddress(https://github.com/alibaba/easyexcel);hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);// 设置备注WriteCellDataString comment new WriteCellData(备注的单元格信息);writeCellDemoData.setCommentData(comment);CommentData commentData new CommentData();comment.setCommentData(commentData);commentData.setAuthor(Jiaju Zhuang);commentData.setRichTextStringData(new RichTextStringData(这是一个备注));// 备注的默认大小是按照单元格的大小 这里想调整到4个单元格那么大 所以向后 向下 各额外占用了一个单元格commentData.setRelativeLastColumnIndex(1);commentData.setRelativeLastRowIndex(1);// 设置公式WriteCellDataString formula new WriteCellData();writeCellDemoData.setFormulaData(formula);FormulaData formulaData new FormulaData();formula.setFormulaData(formulaData);// 将 123456789 中的第一个数字替换成 2// 这里只是例子 如果真的涉及到公式 能内存算好尽量内存算好 公式能不用尽量不用formulaData.setFormulaValue(REPLACE(123456789,1,1,2));// 设置单个单元格的样式 当然样式 很多的话 也可以用注解等方式。WriteCellDataString writeCellStyle new WriteCellData(单元格样式);writeCellStyle.setType(CellDataTypeEnum.STRING);writeCellDemoData.setWriteCellStyle(writeCellStyle);WriteCellStyle writeCellStyleData new WriteCellStyle();writeCellStyle.setWriteCellStyle(writeCellStyleData);// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.writeCellStyleData.setFillPatternType(FillPatternType.SOLID_FOREGROUND);// 背景绿色writeCellStyleData.setFillForegroundColor(IndexedColors.GREEN.getIndex());// 设置单个单元格多种样式// 这里需要设置 inMomerytrue 不然会导致无法展示单个单元格多种样式所以慎用WriteCellDataString richTest new WriteCellData();richTest.setType(CellDataTypeEnum.RICH_TEXT_STRING);writeCellDemoData.setRichText(richTest);RichTextStringData richTextStringData new RichTextStringData();richTest.setRichTextStringDataValue(richTextStringData);richTextStringData.setTextString(红色绿色默认);// 前2个字红色WriteFont writeFont new WriteFont();writeFont.setColor(IndexedColors.RED.getIndex());richTextStringData.applyFont(0, 2, writeFont);// 接下来2个字绿色writeFont new WriteFont();writeFont.setColor(IndexedColors.GREEN.getIndex());richTextStringData.applyFont(2, 4, writeFont);ListWriteCellDemoData data new ArrayList();data.add(writeCellDemoData);EasyExcel.write(fileName, WriteCellDemoData.class).inMemory(true).sheet(模板).doWrite(data);}/*** 根据模板写入模板文件的方式可以动态变化模板了解模板书写规范即可* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 使用{link ExcelProperty}注解指定写入的列* p* 3. 使用withTemplate 写取模板* p* 4. 直接写即可*/public void templateWrite() {String templateFileName demo File.separator demo.xlsx;String fileName templateWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭// 这里要注意 withTemplate 的模板文件会全量存储在内存里面所以尽量不要用于追加文件如果文件模板文件过大会OOM// 如果要再文件中追加无法在一个线程里面处理可以在一个线程的建议参照多次写入的demo 建议临时存储到数据库 或者 磁盘缓存(ehcache) 然后再一次性写入EasyExcel.write(fileName, User.class).withTemplate(templateFileName).sheet().doWrite(data());}/*** 列宽、行高* p* 1. 创建excel对应的实体对象 参照{link WidthAndHeightData}* p* 2. 使用注解{link ColumnWidth}、{link HeadRowHeight}、{link ContentRowHeight}指定宽度或高度* p* 3. 直接写即可*/public void widthAndHeightWrite() {String fileName widthAndHeightWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, WidthAndHeightData.class).sheet(模板).doWrite(data());}/*** 注解形式自定义样式* p* 1. 创建excel对应的实体对象 参照{link FixStyleData}* p* 3. 直接写即可** since 2.2.0-beta1*/public void annotationStyleWrite() {String fileName annotationStyleWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, FixStyleData.class).sheet(模板).doWrite(data());}/*** 拦截器形式自定义样式* p* 1. 创建excel对应的实体对象 参照{link DemoData}* p* 2. 创建一个style策略 并注册* p* 3. 直接写即可*/public void handlerStyleWrite() {// 方法1 使用已有的策略 推荐// HorizontalCellStyleStrategy 每一行的样式都一样 或者隔行一样// AbstractVerticalCellStyleStrategy 每一列的样式都一样 需要自己回调每一页String fileName handlerStyleWrite 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, User.class).registerWriteHandler(horizontalCellStyleStrategy).sheet(模板).doWrite(data());// 方法2: 使用easyexcel的方式完全自己写 不太推荐 尽量使用已有策略// since 3.0.0-beta2fileName handlerStyleWrite System.currentTimeMillis() .xlsx;EasyExcel.write(fileName, User.class).registerWriteHandler(new CellWriteHandler() {Overridepublic void afterCellDispose(CellWriteHandlerContext context) {// 当前事件会在 数据设置到poi的cell里面才会回调// 判断不是头的情况 如果是fill 的情况 这里会null 所以用not trueif (BooleanUtils.isNotTrue(context.getHead())) {// 第一个单元格// 只要不是头 一定会有数据 当然fill的情况 可能要context.getCellDataList() ,这个需要看模板因为一个单元格会有多个 WriteCellDataWriteCellData? cellData context.getFirstCellData();// 这里需要去cellData 获取样式// 很重要的一个原因是 WriteCellStyle 和 dataFormatData绑定的 简单的说 比如你加了 DateTimeFormat// 已经将writeCellStyle里面的dataFormatData 改了 如果你自己new了一个WriteCellStyle可能注解的样式就失效了// 然后 getOrCreateStyle 用于返回一个样式如果为空则创建一个后返回WriteCellStyle writeCellStyle cellData.getOrCreateStyle();writeCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUNDwriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);// 这样样式就设置好了 后面有个FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到 cell里面去 所以可以不用管了}}}).sheet(模板).doWrite(data());// 方法3: 使用poi的样式完全自己写 不推荐// since 3.0.0-beta2// 坑1style里面有dataformat 用来格式化数据的 所以自己设置可能导致格式化注解不生效// 坑2不要一直去创建style 记得缓存起来 最多创建6W个就挂了fileName handlerStyleWrite System.currentTimeMillis() .xlsx;EasyExcel.write(fileName, User.class).registerWriteHandler(new CellWriteHandler() {Overridepublic void afterCellDispose(CellWriteHandlerContext context) {// 当前事件会在 数据设置到poi的cell里面才会回调// 判断不是头的情况 如果是fill 的情况 这里会null 所以用not trueif (BooleanUtils.isNotTrue(context.getHead())) {Cell cell context.getCell();// 拿到poi的workbookWorkbook workbook context.getWriteWorkbookHolder().getWorkbook();// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式// 不同单元格尽量传同一个 cellStyleCellStyle cellStyle workbook.createCellStyle();cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUNDcellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);cell.setCellStyle(cellStyle);// 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确// 这里要把 WriteCellData的样式清空 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到// cell里面去 会导致自己设置的不一样context.getFirstCellData().setWriteCellStyle(null);}}}).sheet(模板).doWrite(data());}/*** 合并单元格* p* 1. 创建excel对应的实体对象 参照{link User} {link RowMergeData}* p* 2. 创建一个merge策略 并注册* p* 3. 直接写即可** since 2.2.0-beta1*/public void mergeWrite() {// 方法1 注解String fileName mergeWrite System.currentTimeMillis() .xlsx;// 在DemoStyleData里面加上ContentLoopMerge注解// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, RowMergeData.class).sheet(模板).doWrite(data());// 方法2 自定义合并单元格策略fileName mergeWrite System.currentTimeMillis() .xlsx;// 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度所以就第一列会合并。当然其他合并策略也可以自己写LoopMergeStrategy loopMergeStrategy new LoopMergeStrategy(2, 0);// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, User.class).registerWriteHandler(loopMergeStrategy).sheet(模板).doWrite(data());}/*** 使用table去写入* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 然后写入table即可*/public void tableWrite() {String fileName tableWrite System.currentTimeMillis() .xlsx;// 方法1 这里直接写多个table的案例了如果只有一个 也可以直一行代码搞定参照其他案// 这里 需要指定写用哪个class去写try (ExcelWriter excelWriter EasyExcel.write(fileName, User.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);}}/*** 动态头实时生成头写入* p* 思路是这样子的先创建ListString头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据** p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 然后写入table即可*/public void dynamicHeadWrite() {String fileName dynamicHeadWrite System.currentTimeMillis() .xlsx;EasyExcel.write(fileName)// 这里放入动态头.head(head()).sheet(模板)// 当然这里数据也可以用 ListListString 去传入.doWrite(data());}/*** 自动列宽(不太精确)* p* 这个目前不是很好用比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。 当然也可以自己参照 {link LongestMatchColumnWidthStyleStrategy}* 重新实现.* p* poi 自带{link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。** p* 1. 创建excel对应的实体对象 参照{link LongestMatchColumnWidthData}* p* 2. 注册策略{link LongestMatchColumnWidthStyleStrategy}* p* 3. 直接写即可*/public void longestMatchColumnWidthWrite() {String fileName longestMatchColumnWidthWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, LongestMatchColumnWidthData.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet(模板).doWrite(dataLong());}/*** 下拉超链接等自定义拦截器上面几点都不符合但是要对单元格进行操作的参照这个* p* demo这里实现2点。1. 对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel 2. 对第一列第一行和第二行的数据新增下拉框显示 测试1 测试2* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 注册拦截器 {link CustomSheetWriteHandler}* p* 2. 直接写即可*/public void customHandlerWrite() {String fileName customHandlerWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, User.class).registerWriteHandler(new CustomSheetWriteHandler()).registerWriteHandler(new CustomCellWriteHandler()).sheet(模板).doWrite(data());}/*** 插入批注* p* 1. 创建excel对应的实体对象 参照{link User}* p* 2. 注册拦截器 {link CommentWriteHandler}* p* 2. 直接写即可*/public void commentWrite() {String fileName commentWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭// 这里要注意inMemory 要设置为true才能支持批注。目前没有好的办法解决 不在内存处理批注。这个需要自己选择。EasyExcel.write(fileName, User.class).inMemory(Boolean.TRUE).registerWriteHandler(new CommentWriteHandler()).sheet(模板).doWrite(data());}/*** 可变标题处理(包括标题国际化等)* p* 简单的说用ListListString的标题 但是还支持注解* p* 1. 创建excel对应的实体对象 参照{link UserFormat}* p* 2. 直接写即可*/public void variableTitleWrite() {// 写法1String fileName variableTitleWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, UserFormat.class).head(variableTitleHead()).sheet(模板).doWrite(data());}/*** 不创建对象的写*/public void noModelWrite() {// 写法1String fileName noModelWrite System.currentTimeMillis() .xlsx;// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭EasyExcel.write(fileName).head(head()).sheet(模板).doWrite(dataList());}private ListLongestMatchColumnWidthData dataLong() {ListLongestMatchColumnWidthData list ListUtils.newArrayList();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 ListListString variableTitleHead() {ListListString list ListUtils.newArrayList();ListString head0 ListUtils.newArrayList();head0.add(string System.currentTimeMillis());ListString head1 ListUtils.newArrayList();head1.add(number System.currentTimeMillis());ListString head2 ListUtils.newArrayList();head2.add(date System.currentTimeMillis());list.add(head0);list.add(head1);list.add(head2);return list;}private ListListString head() {ListListString list ListUtils.newArrayList();ListString head0 ListUtils.newArrayList();head0.add(字符串 System.currentTimeMillis());ListString head1 ListUtils.newArrayList();head1.add(数字 System.currentTimeMillis());ListString head2 ListUtils.newArrayList();head2.add(日期 System.currentTimeMillis());list.add(head0);list.add(head1);list.add(head2);return list;}private ListListObject dataList() {ListListObject list ListUtils.newArrayList();for (int i 0; i 10; i) {ListObject data ListUtils.newArrayList();data.add(字符串 i);data.add(0.56);data.add(new Date());list.add(data);}return list;}private ListUser data() {ListUser list ListUtils.newArrayList();for (int i 0; i 10; i) {User data new User();data.setCname(字符串 i);data.setCreateTime(new Date());data.setScore(0.56);list.add(data);}return list;} }以上代码取自官方内的实现自测具体实现类可详见: https://github.com/CzyerChen/springboot-forall/tree/master/boot-for-easyexcel/src/main/java/com/learning/easyexcel 5.3 常规WEB的上传和下载 这个文件的接口和回写基本就是引用过Read和Write的具体方法参照官方的书写方式 https://github.com/alibaba/easyexcel/blob/master/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java /*** 文件下载失败了会返回一个有部分数据的Excel* p* 1. 创建excel对应的实体对象 参照{link DownloadData}* p* 2. 设置返回的 参数* p* 3. 直接写这里注意finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大*/GetMapping(download)public void download(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题请直接用浏览器或者用postmanresponse.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet);response.setCharacterEncoding(utf-8);// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName URLEncoder.encode(测试, UTF-8).replaceAll(\\, %20);response.setHeader(Content-disposition, attachment;filename*utf-8 fileName .xlsx);EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet(模板).doWrite(data());}/*** 文件上传* p1. 创建excel对应的实体对象 参照{link UploadData}* p2. 由于默认一行行的读取excel所以需要创建excel一行一行的回调监听器参照{link UploadDataListener}* p3. 直接读即可*/PostMapping(upload)ResponseBodypublic String upload(MultipartFile file) throws IOException {EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead();return success;}
http://www.tj-hxxt.cn/news/130475.html

相关文章:

  • 设计网站的软件如何查看网站开发语言
  • 做推广的网站吗企业app定制开发
  • 安平网站建设网上营销的概念
  • dw+如何做自适应网站做区块链的网站
  • 如何做外贸品牌网站建设句容建设工程备案网站
  • 南阳做网站aokuo《基层建设》官方网站
  • 闵行广州网站建设百度seo排名如何提升
  • 哪里网站备案最快在线做字网站
  • 做企业网站的代码张家港网站设计建设
  • 西安网站设计建设公司 交通做网站要学些什么软件
  • 现在网站做多宽crm管理系统
  • 专业网站快速wordpress建图片网站
  • 用ps做零食网站模板网站顶部怎么做新浪链接
  • 违禁网站用什么浏览器宝安专业做网站
  • 网站图片如何做超链接怎么做下载类的网站
  • php自己做网站访问量计算淮北论坛最新招聘
  • 城乡住房建设厅网站首页移动终端开发
  • 无锡品牌网站建设培训网站系统建设
  • 滑县网站建设wordpress部署php
  • 商业网站的创建程序网站更改了资料 百度什么时侯来抓取
  • 昆明网站建设在河科技如何使用二级域名做网站
  • asp网站攻击网站开发实验总结
  • 做网站支付系统难度wordpress homepage plugin
  • 网站首页html代码的标签怎样打开用sql做的网站
  • 网站seo优化如何做佛山企业网站制作公司
  • 龙岩做网站开发哪家做的好网页动效 wordpress
  • 营销型企业网站分析与诊断虚拟网站php专业型
  • 垂直网站 开源码邵阳小学网站建设
  • 东莞做网站最好有哪些公司flask公司网站开发
  • 网站用户引导在阿里云做视频网站需要什么