diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 724ecec4..997623f6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,7 @@ ## 提前沟通 尽量把自己的想法和实现思路提前沟通,可以通过issue,钉钉,QQ都可以,可能很多问题我们内部已经讨论过,由于各种原因后续不会支持,但是您这边又开发好了,这样容易浪费您的时间。 ## 代码规范 +请先安装阿里巴巴代码规约插件!!!https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines 目前代码规范已经集成了自动校验,然后源代码尽量不要有中文注释。在新增功能的时候,尽量注意补充junit。core代表每次travis-ci都会跑的测试案例,然后demo用于对外看到,temp里面随便写。 ## 提交分支 建议提交到最新的版本号.x上面,比如 3.x之类的版本,为了方便其他同学阅读源代码,所以目前的思路是master和maven center的最新版本代码保持一致,然后您提交过来的代码我们可能会稍微做一些修改。所以提交到开发分支会比较好。fork也可以直接fork该分支。 diff --git a/README.md b/README.md index e961d412..9edcc142 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,32 @@ EasyExcel #### 因为公司不方便用QQ,所以建议加钉钉群 # JAVA解析Excel工具EasyExcel -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模式。在上层做了模型转换的封装,让使用者更加简单方便 +Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便 ## 64M内存1分钟内读取75M(46W行25列)的Excel -当然还有急速模式能更快,但是内存占用会在100M多一点 +当然还有极速模式能更快,但是内存占用会在100M多一点 ![img](img/readme/large.png) +## 版本支持 +* 2+ 版本支持 Java7和Java6 +* 3+ 版本至少 Java8 +### 关于版本升级 +* 不建议夸大版本升级 尤其夸2个大版本 +* 2+ 升级到 3+ + * 使用了自定义拦截器去修改样式的会出问题 + * 读的时候`invoke`里面抛出异常,不会再额外封装一层`ExcelAnalysisException` +* 大版本升级后建议相关内容重新测试下 + +## 人员招募 +由于工作较忙,有意愿做开源的同学可以报名,主要负责群里回答&issue处理,当然也可以做一些PR. +由于开源没有任何物质回报,然后现在的维护同学也是课余时间维护的,所以想加入的同学需要持之以恒,而不是一时兴起. +要求如下: +* 有一定java编码能力 & 良好的编码习惯 +* 了解easyexcel 读&写的原理 +* 热爱开源项目 +* 能长期坚持的去做 +* 相对工作没那么忙 + ## 相关文档 * [快速开始](https://www.yuque.com/easyexcel/doc/easyexcel) * [关于软件](/abouteasyexcel.md) @@ -83,7 +103,7 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja @GetMapping("download") public void download(HttpServletResponse response) throws IOException { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman - response.setContentType("application/vnd.ms-excel"); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20"); diff --git a/lombok.config b/lombok.config new file mode 100644 index 00000000..50dfe616 --- /dev/null +++ b/lombok.config @@ -0,0 +1,2 @@ +lombok.toString.callSuper = CALL +lombok.equalsAndHashCode.callSuper= CALL \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6be301da..3f29ad91 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.alibaba easyexcel - 2.2.11 + 3.0.0-beta1 jar easyexcel @@ -16,7 +16,7 @@ UTF-8 - 1.6 + 1.8 true true @@ -60,68 +60,74 @@ org.apache.poi poi - 3.17 + 4.1.2 org.apache.poi poi-ooxml - 3.17 + 4.1.2 org.apache.poi poi-ooxml-schemas - 3.17 + 4.1.2 + + + org.apache.commons + commons-csv + 1.8 cglib cglib - 3.1 + 3.3.0 org.slf4j slf4j-api - 1.7.26 + 1.7.32 org.ehcache ehcache - 3.4.0 + 3.8.1 + + org.projectlombok + lombok + 1.18.20 + provided + + ch.qos.logback logback-classic - 1.2.3 + 1.2.5 test com.alibaba fastjson - 1.2.71 - test - - - org.projectlombok - lombok - 1.18.8 + 1.2.78 test org.springframework.boot spring-boot - 1.5.21.RELEASE + 2.5.4 test org.springframework.boot spring-boot-starter-web - 1.5.21.RELEASE + 2.5.4 test junit junit - 4.12 + 4.13.2 test @@ -162,8 +168,11 @@ com/alibaba/excel/event/AnalysisEventListener.java com/alibaba/excel/metadata/DataFormatter.java com/alibaba/excel/util/DateUtils.java + com/alibaba/excel/util/MapUtils.java com/alibaba/excel/metadata/format/DataFormatter.java com/alibaba/excel/metadata/format/ExcelGeneralNumberFormat.java + com/alibaba/excel/metadata/csv/CsvDataFormat.java + com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -186,14 +195,16 @@ org.apache.maven.plugins maven-compiler-plugin + 3.8.1 - 1.6 - 1.6 + 1.8 + 1.8 + org.apache.maven.plugins maven-source-plugin - 2.1 + 3.2.1 true @@ -232,6 +243,30 @@ + + org.projectlombok + lombok-maven-plugin + 1.18.20.0 + + + generate-sources + + delombok + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + com/alibaba/easyexcel/test/core/**/*.java + + true + + diff --git a/src/main/java/com/alibaba/excel/EasyExcelFactory.java b/src/main/java/com/alibaba/excel/EasyExcelFactory.java index a4924973..ef9b3ac3 100644 --- a/src/main/java/com/alibaba/excel/EasyExcelFactory.java +++ b/src/main/java/com/alibaba/excel/EasyExcelFactory.java @@ -3,17 +3,10 @@ package com.alibaba.excel; import java.io.File; import java.io.InputStream; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.excel.event.WriteHandler; -import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.read.builder.ExcelReaderBuilder; import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder; import com.alibaba.excel.read.listener.ReadListener; -import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.builder.ExcelWriterBuilder; import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; import com.alibaba.excel.write.builder.ExcelWriterTableBuilder; @@ -39,138 +32,6 @@ import com.alibaba.excel.write.builder.ExcelWriterTableBuilder; */ public class EasyExcelFactory { - /** - * Quickly read small files,no more than 10,000 lines. - * - * @param in - * the POI filesystem that contains the Workbook stream. - * @param sheet - * read sheet. - * @return analysis result. - * @deprecated please use 'EasyExcel.read(in).sheet(sheetNo).doReadSync();' - */ - @Deprecated - public static List read(InputStream in, Sheet sheet) { - final List rows = new ArrayList(); - new ExcelReader(in, null, new AnalysisEventListener() { - @Override - public void invoke(Object object, AnalysisContext context) { - rows.add(object); - } - - @Override - public void doAfterAllAnalysed(AnalysisContext context) {} - }, false).read(sheet); - return rows; - } - - /** - * Parsing large file - * - * @param in - * the POI filesystem that contains the Workbook stream. - * @param sheet - * read sheet. - * @param listener - * Callback method after each row is parsed. - * @deprecated please use 'EasyExcel.read(in,head,listener).sheet(sheetNo).doRead();' - */ - @Deprecated - public static void readBySax(InputStream in, Sheet sheet, AnalysisEventListener listener) { - new ExcelReader(in, null, listener).read(sheet); - } - - /** - * Get ExcelReader. - * - * @param in - * the POI filesystem that contains the Workbook stream. - * @param listener - * Callback method after each row is parsed. - * @return ExcelReader. - * @deprecated please use {@link EasyExcel#read()} build 'ExcelReader' - */ - @Deprecated - public static ExcelReader getReader(InputStream in, AnalysisEventListener listener) { - return new ExcelReader(in, null, listener); - } - - /** - * Get ExcelWriter - * - * @param outputStream - * the java OutputStream you wish to write the value to. - * @return new ExcelWriter. - * @deprecated please use {@link EasyExcel#write()} - */ - @Deprecated - public static ExcelWriter getWriter(OutputStream outputStream) { - return write().file(outputStream).autoCloseStream(Boolean.FALSE).convertAllFiled(Boolean.FALSE).build(); - } - - /** - * Get ExcelWriter - * - * @param outputStream - * the java OutputStream you wish to write the value to. - * @param typeEnum - * 03 or 07 - * @param needHead - * Do you need to write the header to the file? - * @return new ExcelWriter - * @deprecated please use {@link EasyExcel#write()} - */ - @Deprecated - public static ExcelWriter getWriter(OutputStream outputStream, ExcelTypeEnum typeEnum, boolean needHead) { - return write().file(outputStream).excelType(typeEnum).needHead(needHead).autoCloseStream(Boolean.FALSE) - .convertAllFiled(Boolean.FALSE).build(); - } - - /** - * Get ExcelWriter with a template file - * - * @param temp - * Append value after a POI file , Can be null(the template POI filesystem that contains the Workbook - * stream) - * @param outputStream - * the java OutputStream you wish to write the value to - * @param typeEnum - * 03 or 07 - * @param needHead - * Whether a write header is required - * @return new ExcelWriter - * @deprecated please use {@link EasyExcel#write()} - */ - @Deprecated - public static ExcelWriter getWriterWithTemp(InputStream temp, OutputStream outputStream, ExcelTypeEnum typeEnum, - boolean needHead) { - return write().withTemplate(temp).file(outputStream).excelType(typeEnum).needHead(needHead) - .autoCloseStream(Boolean.FALSE).convertAllFiled(Boolean.FALSE).build(); - } - - /** - * Get ExcelWriter with a template file - * - * @param temp - * Append value after a POI file , Can be null(the template POI filesystem that contains the Workbook - * stream) - * @param outputStream - * the java OutputStream you wish to write the value to - * @param typeEnum - * 03 or 07 - * @param needHead - * Whether a write header is required - * @param handler - * User-defined callback - * @return new ExcelWriter - * @deprecated please use {@link EasyExcel#write()} - */ - @Deprecated - public static ExcelWriter getWriterWithTempAndHandler(InputStream temp, OutputStream outputStream, - ExcelTypeEnum typeEnum, boolean needHead, WriteHandler handler) { - return write().withTemplate(temp).file(outputStream).excelType(typeEnum).needHead(needHead) - .registerWriteHandler(handler).autoCloseStream(Boolean.FALSE).convertAllFiled(Boolean.FALSE).build(); - } /** * Build excel the write diff --git a/src/main/java/com/alibaba/excel/ExcelReader.java b/src/main/java/com/alibaba/excel/ExcelReader.java index 7af49eb6..a1a9c50d 100644 --- a/src/main/java/com/alibaba/excel/ExcelReader.java +++ b/src/main/java/com/alibaba/excel/ExcelReader.java @@ -1,25 +1,17 @@ package com.alibaba.excel; -import java.io.InputStream; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.analysis.ExcelAnalyser; import com.alibaba.excel.analysis.ExcelAnalyserImpl; import com.alibaba.excel.analysis.ExcelReadExecutor; -import com.alibaba.excel.cache.MapCache; import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.excel.metadata.Sheet; -import com.alibaba.excel.parameter.AnalysisParam; -import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadWorkbook; -import com.alibaba.excel.support.ExcelTypeEnum; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Excel readers are all read in event mode. @@ -34,113 +26,6 @@ public class ExcelReader { */ private ExcelAnalyser excelAnalyser; - /** - * Create new reader - * - * @param in - * the POI filesystem that contains the Workbook stream - * @param excelTypeEnum - * 03 or 07 - * @param customContent - * {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext - * @param eventListener - * Callback method after each row is parsed. - * @deprecated please use {@link EasyExcelFactory#read()} build 'ExcelReader' - */ - @Deprecated - public ExcelReader(InputStream in, ExcelTypeEnum excelTypeEnum, Object customContent, - AnalysisEventListener eventListener) { - this(in, excelTypeEnum, customContent, eventListener, true); - } - - /** - * Create new reader - * - * @param in - * the POI filesystem that contains the Workbook stream - * @param customContent - * {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext - * @param eventListener - * Callback method after each row is parsed - * @deprecated please use {@link EasyExcelFactory#read()} build 'ExcelReader' - */ - @Deprecated - public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener) { - this(in, customContent, eventListener, true); - } - - /** - * Create new reader - * - * @param param - * old param Deprecated - * @param eventListener - * Callback method after each row is parsed. - * @deprecated please use {@link EasyExcelFactory#read()} build 'ExcelReader' - */ - @Deprecated - public ExcelReader(AnalysisParam param, AnalysisEventListener eventListener) { - this(param.getIn(), param.getExcelTypeEnum(), param.getCustomContent(), eventListener, true); - } - - /** - * Create new reader - * - * @param in - * @param customContent - * {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext - * @param eventListener - * @param trim - * The content of the form is empty and needs to be empty. The purpose is to be fault-tolerant, because - * there are often table contents with spaces that can not be converted into custom types. For example: - * '1234 ' contain a space cannot be converted to int. - * @deprecated please use {@link EasyExcelFactory#read()} build 'ExcelReader' - */ - @Deprecated - public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener, boolean trim) { - this(in, null, customContent, eventListener, trim); - } - - /** - * Create new reader - * - * @param in - * the POI filesystem that contains the Workbook stream - * @param excelTypeEnum - * 03 or 07 - * @param customContent - * {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext - * @param eventListener - * Callback method after each row is parsed. - * @param trim - * The content of the form is empty and needs to be empty. The purpose is to be fault-tolerant, because - * there are often table contents with spaces that can not be converted into custom types. For example: - * '1234 ' contain a space cannot be converted to int. - * @deprecated please use {@link EasyExcelFactory#read()} build 'ExcelReader' - */ - @Deprecated - public ExcelReader(InputStream in, ExcelTypeEnum excelTypeEnum, Object customContent, - AnalysisEventListener eventListener, boolean trim) { - ReadWorkbook readWorkbook = new ReadWorkbook(); - readWorkbook.setInputStream(in); - readWorkbook.setExcelType(excelTypeEnum); - readWorkbook.setCustomObject(customContent); - if (eventListener != null) { - List customReadListenerList = new ArrayList(); - customReadListenerList.add(eventListener); - readWorkbook.setCustomReadListenerList(customReadListenerList); - } - readWorkbook.setAutoTrim(trim); - readWorkbook.setAutoCloseStream(Boolean.FALSE); - readWorkbook.setMandatoryUseInputStream(Boolean.TRUE); - readWorkbook.setReadCache(new MapCache()); - readWorkbook.setConvertAllFiled(Boolean.FALSE); - readWorkbook.setDefaultReturnMap(Boolean.FALSE); - // The previous logic was that Article 0 started reading - readWorkbook.setHeadRowNumber(0); - excelAnalyser = new ExcelAnalyserImpl(readWorkbook); - } - public ExcelReader(ReadWorkbook readWorkbook) { excelAnalyser = new ExcelAnalyserImpl(readWorkbook); } @@ -183,44 +68,6 @@ public class ExcelReader { return this; } - /** - * Parse the specified sheet,SheetNo start from 1 - * - * @param sheet - * Read sheet - * @deprecated please us {@link #read(ReadSheet...)} - */ - @Deprecated - public void read(Sheet sheet) { - ReadSheet readSheet = null; - if (sheet != null) { - readSheet = new ReadSheet(); - readSheet.setSheetNo(sheet.getSheetNo() - 1); - readSheet.setSheetName(sheet.getSheetName()); - readSheet.setClazz(sheet.getClazz()); - readSheet.setHead(sheet.getHead()); - readSheet.setHeadRowNumber(sheet.getHeadLineMun()); - } - read(readSheet); - } - - /** - * Parse the specified sheet - * - * @param sheet - * Read sheet - * @param clazz - * object parsed into each row of value - * - * @deprecated Set the class in the sheet before read - */ - @Deprecated - public void read(Sheet sheet, Class clazz) { - if (sheet != null) { - sheet.setClazz(clazz); - } - read(sheet); - } /** * Context for the entire execution process @@ -240,28 +87,6 @@ public class ExcelReader { return excelAnalyser.excelExecutor(); } - /** - * Parse the workBook get all sheets - * - * @return workBook all sheets - * - * @deprecated please use {@link #excelExecutor()} - */ - @Deprecated - public List getSheets() { - List sheetList = excelExecutor().sheetList(); - List sheets = new ArrayList(); - if (sheetList == null || sheetList.isEmpty()) { - return sheets; - } - for (ReadSheet readSheet : sheetList) { - Sheet sheet = new Sheet(readSheet.getSheetNo() + 1); - sheet.setSheetName(readSheet.getSheetName()); - sheets.add(sheet); - } - return sheets; - } - /** * * @return diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index 0eafecde..bfdf2f26 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -1,27 +1,19 @@ package com.alibaba.excel; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.Collection; +import java.util.function.Supplier; import com.alibaba.excel.context.WriteContext; -import com.alibaba.excel.metadata.Sheet; -import com.alibaba.excel.metadata.Table; -import com.alibaba.excel.parameter.GenerateParam; -import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.ExcelBuilder; import com.alibaba.excel.write.ExcelBuilderImpl; -import com.alibaba.excel.write.handler.WriteHandler; -import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteWorkbook; import com.alibaba.excel.write.metadata.fill.FillConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Excel Writer This tool is used to write value out to Excel via POI. This object can perform the following two * functions. @@ -48,117 +40,50 @@ public class ExcelWriter { } /** - * Create new writer - * - * @param outputStream - * the java OutputStream you wish to write the value to - * @param typeEnum - * 03 or 07 - * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter - */ - @Deprecated - public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum) { - this(outputStream, typeEnum, true); - } - - /** - * - * Create new writer - * - * @param outputStream - * the java OutputStream you wish to write the value to - * @param typeEnum - * 03 or 07 - * @param needHead - * Do you need to write the header to the file? - * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter - */ - @Deprecated - public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum, boolean needHead) { - this(null, outputStream, typeEnum, needHead, null); - } - - /** - * Create new writer + * Write data to a sheet * - * @param templateInputStream - * Append value after a POI file ,Can be null(the template POI filesystem that contains the Workbook - * stream) - * @param outputStream - * the java OutputStream you wish to write the value to - * @param typeEnum - * 03 or 07 - * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter + * @param data Data to be written + * @param writeSheet Write to this sheet + * @return this current writer */ - @Deprecated - public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum, - Boolean needHead) { - this(templateInputStream, outputStream, typeEnum, needHead, null); + public ExcelWriter write(Collection data, WriteSheet writeSheet) { + return write(data, writeSheet, null); } /** - * Create new writer + * Write data to a sheet * - * @param templateInputStream - * Append value after a POI file ,Can be null(the template POI filesystem that contains the Workbook - * stream) - * @param outputStream - * the java OutputStream you wish to write the value to - * @param typeEnum - * 03 or 07 - * @param writeHandler - * User-defined callback - * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter - */ - @Deprecated - public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum, - Boolean needHead, WriteHandler writeHandler) { - List customWriteHandlerList = new ArrayList(); - customWriteHandlerList.add(writeHandler); - WriteWorkbook writeWorkbook = new WriteWorkbook(); - writeWorkbook.setTemplateInputStream(templateInputStream); - writeWorkbook.setOutputStream(outputStream); - writeWorkbook.setExcelType(typeEnum); - writeWorkbook.setNeedHead(needHead); - writeWorkbook.setCustomWriteHandlerList(customWriteHandlerList); - excelBuilder = new ExcelBuilderImpl(writeWorkbook); - } - - /** - * @param generateParam - * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter + * @param supplier Data to be written + * @param writeSheet Write to this sheet + * @return this current writer */ - @Deprecated - public ExcelWriter(GenerateParam generateParam) { - this(generateParam.getOutputStream(), generateParam.getType(), true); + public ExcelWriter write(Supplier> supplier, WriteSheet writeSheet) { + return write(supplier.get(), writeSheet, null); } /** - * Write data to a sheet + * Write value to a sheet * - * @param data - * Data to be written - * @param writeSheet - * Write to this sheet - * @return this current writer + * @param data Data to be written + * @param writeSheet Write to this sheet + * @param writeTable Write to this table + * @return this */ - public ExcelWriter write(List data, WriteSheet writeSheet) { - return write(data, writeSheet, null); + public ExcelWriter write(Collection data, WriteSheet writeSheet, WriteTable writeTable) { + excelBuilder.addContent(data, writeSheet, writeTable); + return this; } /** * Write value to a sheet * - * @param data - * Data to be written - * @param writeSheet - * Write to this sheet - * @param writeTable - * Write to this table + * @param supplier Data to be written + * @param writeSheet Write to this sheet + * @param writeTable Write to this table * @return this */ - public ExcelWriter write(List data, WriteSheet writeSheet, WriteTable writeTable) { - excelBuilder.addContent(data, writeSheet, writeTable); + public ExcelWriter write(Supplier> supplier, WriteSheet writeSheet, WriteTable writeTable) { + excelBuilder.addContent(supplier.get(), writeSheet, writeTable); return this; } @@ -187,137 +112,26 @@ public class ExcelWriter { } /** - * Write data to a sheet - * - * @param data - * Data to be written - * @param sheet - * Write to this sheet - * @return this current writer - * @deprecated please use {@link ExcelWriter#write(List, WriteSheet)} - */ - @Deprecated - public ExcelWriter write(List data, Sheet sheet) { - return write(data, sheet, null); - } - - /** - * Write value to a sheet - * - * @param data - * Data to be written - * @param sheet - * Write to this sheet - * @param table - * Write to this table - * @return this - * @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)} - */ - @Deprecated - public ExcelWriter write(List data, Sheet sheet, Table table) { - WriteSheet writeSheet = null; - if (sheet != null) { - writeSheet = new WriteSheet(); - writeSheet.setSheetNo(sheet.getSheetNo() - 1); - writeSheet.setSheetName(sheet.getSheetName()); - writeSheet.setClazz(sheet.getClazz()); - writeSheet.setHead(sheet.getHead()); - writeSheet.setTableStyle(sheet.getTableStyle()); - writeSheet.setRelativeHeadRowIndex(sheet.getStartRow()); - writeSheet.setColumnWidthMap(sheet.getColumnWidthMap()); - } - - WriteTable writeTable = null; - if (table != null) { - writeTable = new WriteTable(); - writeTable.setTableNo(table.getTableNo()); - writeTable.setClazz(table.getClazz()); - writeTable.setHead(table.getHead()); - writeTable.setTableStyle(table.getTableStyle()); - } - return write(data, writeSheet, writeTable); - } - - /** - * Write data to a sheet - * - * @param data - * Data to be written - * @param sheet - * Write to this sheet - * @return this current writer - * @deprecated please use {@link ExcelWriter#write(List, WriteSheet)} - */ - @Deprecated - public ExcelWriter write0(List data, Sheet sheet) { - return write(data, sheet, null); - } - - /** - * Write value to a sheet - * - * @param data - * Data to be written - * @param sheet - * Write to this sheet - * @param table - * Write to this table - * @return this - * @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)} - */ - @Deprecated - public ExcelWriter write0(List data, Sheet sheet, Table table) { - return write(data, sheet, table); - } - - /** - * Write data to a sheet - * - * @param data - * Data to be written - * @param sheet - * Write to this sheet - * @return this current writer - * @deprecated please use {@link ExcelWriter#write(List, WriteSheet)} - */ - @Deprecated - public ExcelWriter write1(List data, Sheet sheet) { - return write(data, sheet, null); - } - - /** - * Write value to a sheet + * Fill value to a sheet * - * @param data - * Data to be written - * @param sheet - * Write to this sheet - * @param table - * Write to this table - * @return this - * @deprecated * @deprecated please use {@link ExcelWriter#write(List, WriteSheet,WriteTable)} + * @param supplier + * @param writeSheet + * @return */ - @Deprecated - public ExcelWriter write1(List data, Sheet sheet, Table table) { - return write(data, sheet, table); + public ExcelWriter fill(Supplier supplier, WriteSheet writeSheet) { + return fill(supplier.get(), null, writeSheet); } /** - * Merge Cells,Indexes are zero-based. + * Fill value to a sheet * - * @param firstRow - * Index of first row - * @param lastRow - * Index of last row (inclusive), must be equal to or larger than {@code firstRow} - * @param firstCol - * Index of first column - * @param lastCol - * Index of last column (inclusive), must be equal to or larger than {@code firstCol} - * @deprecated please use{@link OnceAbsoluteMergeStrategy} + * @param supplier + * @param fillConfig + * @param writeSheet + * @return */ - @Deprecated - public ExcelWriter merge(int firstRow, int lastRow, int firstCol, int lastCol) { - excelBuilder.merge(firstRow, lastRow, firstCol, lastCol); + public ExcelWriter fill(Supplier supplier, FillConfig fillConfig, WriteSheet writeSheet) { + excelBuilder.fill(supplier.get(), fillConfig, writeSheet); return this; } @@ -332,7 +146,6 @@ public class ExcelWriter { /** * Prevents calls to {@link #finish} from freeing the cache - * */ @Override protected void finalize() { diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java index 5487ee10..743daab9 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java @@ -3,17 +3,12 @@ package com.alibaba.excel.analysis; import java.io.InputStream; import java.util.List; -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; -import org.apache.poi.poifs.crypt.Decryptor; -import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import com.alibaba.excel.analysis.csv.CsvExcelReadExecutor; import com.alibaba.excel.analysis.v03.XlsSaxAnalyser; import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser; import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.context.csv.CsvReadContext; +import com.alibaba.excel.context.csv.DefaultCsvReadContext; import com.alibaba.excel.context.xls.DefaultXlsReadContext; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.context.xlsx.DefaultXlsxReadContext; @@ -26,12 +21,20 @@ import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder; import com.alibaba.excel.support.ExcelTypeEnum; -import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.NumberDataFormatterUtils; import com.alibaba.excel.util.StringUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author jipengfei */ @@ -98,6 +101,11 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { analysisContext = xlsxReadContext; excelReadExecutor = new XlsxSaxAnalyser(xlsxReadContext, null); break; + case CSV: + CsvReadContext csvReadContext = new DefaultCsvReadContext(readWorkbook, ExcelTypeEnum.CSV); + analysisContext = csvReadContext; + excelReadExecutor = new CsvExcelReadExecutor(csvReadContext); + break; default: break; } diff --git a/src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java b/src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java new file mode 100644 index 00000000..d411ef0d --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java @@ -0,0 +1,122 @@ +package com.alibaba.excel.analysis.csv; + +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.alibaba.excel.analysis.ExcelReadExecutor; +import com.alibaba.excel.context.csv.CsvReadContext; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.enums.RowTypeEnum; +import com.alibaba.excel.exception.ExcelAnalysisException; +import com.alibaba.excel.metadata.Cell; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.read.metadata.holder.ReadRowHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; +import com.alibaba.excel.util.SheetUtils; +import com.alibaba.excel.util.StringUtils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVRecord; + +/** + * read executor + * + * @author zhuangjiaju + */ +@Slf4j +public class CsvExcelReadExecutor implements ExcelReadExecutor { + + private List sheetList; + private CsvReadContext csvReadContext; + + public CsvExcelReadExecutor(CsvReadContext csvReadContext) { + this.csvReadContext = csvReadContext; + sheetList = new ArrayList<>(); + ReadSheet readSheet = new ReadSheet(); + sheetList.add(readSheet); + readSheet.setSheetNo(0); + } + + @Override + public List sheetList() { + return sheetList; + } + + @Override + public void execute() { + Iterable parseRecords; + try { + parseRecords = parseRecords(); + } catch (IOException e) { + throw new ExcelAnalysisException(e); + } + for (ReadSheet readSheet : sheetList) { + readSheet = SheetUtils.match(readSheet, csvReadContext); + if (readSheet == null) { + continue; + } + csvReadContext.currentSheet(readSheet); + + int rowIndex = 0; + + for (CSVRecord record : parseRecords) { + dealRecord(record, rowIndex++); + } + + // The last sheet is read + csvReadContext.analysisEventProcessor().endSheet(csvReadContext); + } + } + + private Iterable parseRecords() throws IOException { + CsvReadWorkbookHolder csvReadWorkbookHolder = csvReadContext.csvReadWorkbookHolder(); + CSVFormat csvFormat = csvReadWorkbookHolder.getCsvFormat(); + + if (csvReadWorkbookHolder.getMandatoryUseInputStream()) { + return csvFormat.parse(new InputStreamReader(csvReadWorkbookHolder.getInputStream())); + } + if (csvReadWorkbookHolder.getFile() != null) { + return csvFormat.parse(new FileReader(csvReadWorkbookHolder.getFile())); + } + return csvFormat.parse(new InputStreamReader(csvReadWorkbookHolder.getInputStream())); + } + + private void dealRecord(CSVRecord record, int rowIndex) { + Map cellMap = new LinkedHashMap<>(); + Iterator cellIterator = record.iterator(); + int columnIndex = 0; + while (cellIterator.hasNext()) { + String cellString = cellIterator.next(); + ReadCellData readCellData = new ReadCellData<>(); + readCellData.setRowIndex(rowIndex); + readCellData.setColumnIndex(columnIndex); + + // csv is an empty string of whether ,, is read or ,"", + if (StringUtils.isNotBlank(cellString)) { + readCellData.setType(CellDataTypeEnum.STRING); + readCellData.setStringValue(cellString); + } else { + readCellData.setType(CellDataTypeEnum.EMPTY); + } + cellMap.put(columnIndex++, readCellData); + } + + RowTypeEnum rowType = MapUtils.isEmpty(cellMap) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA; + ReadRowHolder readRowHolder = new ReadRowHolder(rowIndex, rowType, + csvReadContext.readWorkbookHolder().getGlobalConfiguration(), cellMap); + csvReadContext.readRowHolder(readRowHolder); + + csvReadContext.csvReadSheetHolder().setCellMap(cellMap); + csvReadContext.csvReadSheetHolder().setRowIndex(rowIndex); + csvReadContext.analysisEventProcessor().endRow(csvReadContext); + } +} diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java index e6290eb5..25d1338e 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankRecordHandler.java @@ -1,11 +1,11 @@ package com.alibaba.excel.analysis.v03.handlers; -import org.apache.poi.hssf.record.BlankRecord; -import org.apache.poi.hssf.record.Record; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; + +import org.apache.poi.hssf.record.BlankRecord; +import org.apache.poi.hssf.record.Record; /** * Record handler @@ -18,6 +18,6 @@ public class BlankRecordHandler extends AbstractXlsRecordHandler implements Igno public void processRecord(XlsReadContext xlsReadContext, Record record) { BlankRecord br = (BlankRecord)record; xlsReadContext.xlsReadSheetHolder().getCellMap().put((int)br.getColumn(), - CellData.newEmptyInstance(br.getRow(), (int)br.getColumn())); + ReadCellData.newEmptyInstance(br.getRow(), (int)br.getColumn())); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java index 8d435213..19665907 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoolErrRecordHandler.java @@ -1,12 +1,12 @@ package com.alibaba.excel.analysis.v03.handlers; -import org.apache.poi.hssf.record.BoolErrRecord; -import org.apache.poi.hssf.record.Record; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.enums.RowTypeEnum; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; + +import org.apache.poi.hssf.record.BoolErrRecord; +import org.apache.poi.hssf.record.Record; /** * Record handler @@ -19,7 +19,7 @@ public class BoolErrRecordHandler extends AbstractXlsRecordHandler implements Ig public void processRecord(XlsReadContext xlsReadContext, Record record) { BoolErrRecord ber = (BoolErrRecord)record; xlsReadContext.xlsReadSheetHolder().getCellMap().put((int)ber.getColumn(), - CellData.newInstance(ber.getBooleanValue(), ber.getRow(), (int)ber.getColumn())); + ReadCellData.newInstance(ber.getBooleanValue(), ber.getRow(), (int)ber.getColumn())); xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java index 54a2d1df..8ecc33a4 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java @@ -2,18 +2,18 @@ package com.alibaba.excel.analysis.v03.handlers; import java.util.LinkedHashMap; -import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord; -import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord; -import org.apache.poi.hssf.record.Record; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.metadata.Cell; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; +import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord; +import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord; +import org.apache.poi.hssf.record.Record; + /** * Record handler * @@ -35,7 +35,7 @@ public class DummyRecordHandler extends AbstractXlsRecordHandler implements Igno } else if (record instanceof MissingCellDummyRecord) { MissingCellDummyRecord mcdr = (MissingCellDummyRecord)record; xlsReadSheetHolder.getCellMap().put(mcdr.getColumn(), - CellData.newEmptyInstance(mcdr.getRow(), mcdr.getColumn())); + ReadCellData.newEmptyInstance(mcdr.getRow(), mcdr.getColumn())); } } } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java index f78d4102..f5d7ff0a 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java @@ -3,36 +3,36 @@ package com.alibaba.excel.analysis.v03.handlers; import java.math.BigDecimal; import java.util.Map; -import com.alibaba.excel.enums.RowTypeEnum; -import org.apache.poi.hssf.model.HSSFFormulaParser; -import org.apache.poi.hssf.record.FormulaRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.ss.usermodel.CellType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.constant.BuiltinFormats; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.metadata.Cell; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.data.FormulaData; +import com.alibaba.excel.metadata.data.ReadCellData; + +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.hssf.model.HSSFFormulaParser; +import org.apache.poi.hssf.record.FormulaRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.ss.usermodel.CellType; /** * Record handler * * @author Dan Zheng */ +@Slf4j public class FormulaRecordHandler extends AbstractXlsRecordHandler implements IgnorableXlsRecordHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(FormulaRecordHandler.class); private static final String ERROR = "#VALUE!"; @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { FormulaRecord frec = (FormulaRecord)record; Map cellMap = xlsReadContext.xlsReadSheetHolder().getCellMap(); - CellData tempCellData = new CellData(); + ReadCellData tempCellData = new ReadCellData<>(); tempCellData.setRowIndex(frec.getRow()); tempCellData.setColumnIndex((int)frec.getColumn()); CellType cellType = CellType.forInt(frec.getCachedResultType()); @@ -41,10 +41,11 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig formulaValue = HSSFFormulaParser.toFormulaString(xlsReadContext.xlsReadWorkbookHolder().getHssfWorkbook(), frec.getParsedExpression()); } catch (Exception e) { - LOGGER.debug("Get formula value error.", e); + log.debug("Get formula value error.", e); } - tempCellData.setFormula(Boolean.TRUE); - tempCellData.setFormulaValue(formulaValue); + FormulaData formulaData = new FormulaData(); + formulaData.setFormulaValue(formulaValue); + tempCellData.setFormulaData(formulaData); xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA); switch (cellType) { case STRING: @@ -56,10 +57,11 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig case NUMERIC: tempCellData.setType(CellDataTypeEnum.NUMBER); tempCellData.setNumberValue(BigDecimal.valueOf(frec.getValue())); - Integer dataFormat = + int dataFormat = xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(frec); - tempCellData.setDataFormat(dataFormat); - tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat, + DataFormatData dataFormatData = new DataFormatData(); + dataFormatData.setIndex((short)dataFormat); + dataFormatData.setFormat(BuiltinFormats.getBuiltinFormat(dataFormatData.getIndex(), xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(frec), xlsReadContext.readSheetHolder().getGlobalConfiguration().getLocale())); cellMap.put((int)frec.getColumn(), tempCellData); diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java index 4f63ab0c..a90ad6bb 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java @@ -1,12 +1,12 @@ package com.alibaba.excel.analysis.v03.handlers; -import org.apache.poi.hssf.record.LabelRecord; -import org.apache.poi.hssf.record.Record; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.enums.RowTypeEnum; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; + +import org.apache.poi.hssf.record.LabelRecord; +import org.apache.poi.hssf.record.Record; /** * Record handler @@ -22,7 +22,7 @@ public class LabelRecordHandler extends AbstractXlsRecordHandler implements Igno data = data.trim(); } xlsReadContext.xlsReadSheetHolder().getCellMap().put((int)lrec.getColumn(), - CellData.newInstance(data, lrec.getRow(), (int)lrec.getColumn())); + ReadCellData.newInstance(data, lrec.getRow(), (int)lrec.getColumn())); xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java index 7fb5cd0d..fd464e54 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelSstRecordHandler.java @@ -2,15 +2,15 @@ package com.alibaba.excel.analysis.v03.handlers; import java.util.Map; -import org.apache.poi.hssf.record.LabelSSTRecord; -import org.apache.poi.hssf.record.Record; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.cache.ReadCache; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.metadata.Cell; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; + +import org.apache.poi.hssf.record.LabelSSTRecord; +import org.apache.poi.hssf.record.Record; /** * Record handler @@ -25,18 +25,18 @@ public class LabelSstRecordHandler extends AbstractXlsRecordHandler implements I ReadCache readCache = xlsReadContext.readWorkbookHolder().getReadCache(); Map cellMap = xlsReadContext.xlsReadSheetHolder().getCellMap(); if (readCache == null) { - cellMap.put((int)lsrec.getColumn(), CellData.newEmptyInstance(lsrec.getRow(), (int)lsrec.getColumn())); + cellMap.put((int)lsrec.getColumn(), ReadCellData.newEmptyInstance(lsrec.getRow(), (int)lsrec.getColumn())); return; } String data = readCache.get(lsrec.getSSTIndex()); if (data == null) { - cellMap.put((int)lsrec.getColumn(), CellData.newEmptyInstance(lsrec.getRow(), (int)lsrec.getColumn())); + cellMap.put((int)lsrec.getColumn(), ReadCellData.newEmptyInstance(lsrec.getRow(), (int)lsrec.getColumn())); return; } if (xlsReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) { data = data.trim(); } - cellMap.put((int)lsrec.getColumn(), CellData.newInstance(data, lsrec.getRow(), (int)lsrec.getColumn())); + cellMap.put((int)lsrec.getColumn(), ReadCellData.newInstance(data, lsrec.getRow(), (int)lsrec.getColumn())); xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java index 50608095..1573b8e7 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java @@ -2,14 +2,15 @@ package com.alibaba.excel.analysis.v03.handlers; import java.math.BigDecimal; -import org.apache.poi.hssf.record.NumberRecord; -import org.apache.poi.hssf.record.Record; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.constant.BuiltinFormats; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.enums.RowTypeEnum; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.data.ReadCellData; + +import org.apache.poi.hssf.record.NumberRecord; +import org.apache.poi.hssf.record.Record; /** * Record handler @@ -21,12 +22,16 @@ public class NumberRecordHandler extends AbstractXlsRecordHandler implements Ign @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { NumberRecord nr = (NumberRecord)record; - CellData cellData = CellData.newInstance(BigDecimal.valueOf(nr.getValue()), nr.getRow(), (int)nr.getColumn()); - Integer dataFormat = xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(nr); - cellData.setDataFormat(dataFormat); - cellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat, + ReadCellData cellData = ReadCellData.newInstance(BigDecimal.valueOf(nr.getValue()), nr.getRow(), + (int)nr.getColumn()); + short dataFormat = (short)xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex( + nr); + DataFormatData dataFormatData = new DataFormatData(); + dataFormatData.setIndex(dataFormat); + dataFormatData.setFormat(BuiltinFormats.getBuiltinFormat(dataFormat, xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(nr), xlsReadContext.readSheetHolder().getGlobalConfiguration().getLocale())); + cellData.setDataFormatData(dataFormatData); xlsReadContext.xlsReadSheetHolder().getCellMap().put((int)nr.getColumn(), cellData); xlsReadContext.xlsReadSheetHolder().setTempRowType(RowTypeEnum.DATA); } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java index d8317b37..3fb45899 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/RkRecordHandler.java @@ -1,11 +1,11 @@ package com.alibaba.excel.analysis.v03.handlers; -import org.apache.poi.hssf.record.RKRecord; -import org.apache.poi.hssf.record.Record; - import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; + +import org.apache.poi.hssf.record.RKRecord; +import org.apache.poi.hssf.record.Record; /** * Record handler @@ -18,6 +18,6 @@ public class RkRecordHandler extends AbstractXlsRecordHandler implements Ignorab public void processRecord(XlsReadContext xlsReadContext, Record record) { RKRecord re = (RKRecord)record; xlsReadContext.xlsReadSheetHolder().getCellMap().put((int)re.getColumn(), - CellData.newEmptyInstance(re.getRow(), (int)re.getColumn())); + ReadCellData.newEmptyInstance(re.getRow(), (int)re.getColumn())); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java index 3b95cfdb..4e78a381 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/StringRecordHandler.java @@ -7,7 +7,7 @@ import org.slf4j.LoggerFactory; import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.CellData; import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; /** @@ -23,7 +23,7 @@ public class StringRecordHandler extends AbstractXlsRecordHandler implements Ign // String for formula StringRecord srec = (StringRecord)record; XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder(); - CellData tempCellData = xlsReadSheetHolder.getTempCellData(); + CellDatatempCellData = xlsReadSheetHolder.getTempCellData(); if (tempCellData == null) { LOGGER.warn("String type formula but no value found."); return; diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java index a0a9af0e..329f5250 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java @@ -5,13 +5,31 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import com.alibaba.excel.analysis.ExcelReadExecutor; +import com.alibaba.excel.analysis.v07.handlers.sax.SharedStringsTableHandler; +import com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler; +import com.alibaba.excel.cache.ReadCache; +import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.enums.CellExtraTypeEnum; +import com.alibaba.excel.exception.ExcelAnalysisException; +import com.alibaba.excel.metadata.CellExtra; +import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder; +import com.alibaba.excel.util.FileUtils; +import com.alibaba.excel.util.SheetUtils; +import com.alibaba.excel.util.StringUtils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackagePart; @@ -25,26 +43,13 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr; import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; +import org.xml.sax.SAXException; import org.xml.sax.XMLReader; -import com.alibaba.excel.analysis.ExcelReadExecutor; -import com.alibaba.excel.analysis.v07.handlers.sax.SharedStringsTableHandler; -import com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler; -import com.alibaba.excel.cache.ReadCache; -import com.alibaba.excel.context.xlsx.XlsxReadContext; -import com.alibaba.excel.enums.CellExtraTypeEnum; -import com.alibaba.excel.exception.ExcelAnalysisException; -import com.alibaba.excel.metadata.CellExtra; -import com.alibaba.excel.read.metadata.ReadSheet; -import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder; -import com.alibaba.excel.util.CollectionUtils; -import com.alibaba.excel.util.FileUtils; -import com.alibaba.excel.util.SheetUtils; -import com.alibaba.excel.util.StringUtils; - /** * @author jipengfei */ +@Slf4j public class XlsxSaxAnalyser implements ExcelReadExecutor { private XlsxReadContext xlsxReadContext; @@ -78,7 +83,9 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { XSSFReader xssfReader = new XSSFReader(pkg); analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder); - xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable()); + // set style table + setStylesTable(xlsxReadWorkbookHolder, xssfReader); + sheetList = new ArrayList(); sheetMap = new HashMap(); commentsTableMap = new HashMap(); @@ -101,6 +108,17 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { } } + private void setStylesTable(XlsxReadWorkbookHolder xlsxReadWorkbookHolder, XSSFReader xssfReader) { + try { + xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable()); + } catch (Exception e) { + log.warn( + "Currently excel cannot get style information, but it doesn't affect the data analysis.You can try to" + + " save the file with office again or ignore the current error.", + e); + } + } + private void defaultReadCache(XlsxReadWorkbookHolder xlsxReadWorkbookHolder, PackagePart sharedStringsTablePackagePart) { ReadCache readCache = xlsxReadWorkbookHolder.getReadCacheSelector().readCache(sharedStringsTablePackagePart); @@ -147,9 +165,10 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { xlsxReadWorkbookHolder.setTempFile(readTempFile); File tempFile = new File(readTempFile.getPath(), UUID.randomUUID().toString() + ".xlsx"); if (decryptedStream != null) { - FileUtils.writeToFile(tempFile, decryptedStream); + FileUtils.writeToFile(tempFile, decryptedStream, false); } else { - FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream()); + FileUtils.writeToFile(tempFile, xlsxReadWorkbookHolder.getInputStream(), + xlsxReadWorkbookHolder.getAutoCloseStream()); } return OPCPackage.open(tempFile, PackageAccess.READ); } @@ -177,9 +196,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { xmlReader.setContentHandler(handler); xmlReader.parse(inputSource); inputStream.close(); - } catch (ExcelAnalysisException e) { - throw e; - } catch (Exception e) { + } catch (IOException | ParserConfigurationException | SAXException e) { throw new ExcelAnalysisException(e); } finally { if (inputStream != null) { @@ -215,10 +232,12 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { if (commentsTable == null) { return; } - Map cellComments = commentsTable.getCellComments(); - for (XSSFComment xssfComment : cellComments.values()) { - CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.COMMENT, xssfComment.getString().toString(), - xssfComment.getRow(), xssfComment.getColumn()); + Iterator cellAddresses = commentsTable.getCellAddresses(); + while (cellAddresses.hasNext()) { + CellAddress cellAddress = cellAddresses.next(); + XSSFComment cellComment = commentsTable.findCellComment(cellAddress); + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.COMMENT, cellComment.getString().toString(), + cellAddress.getRow(), cellAddress.getColumn()); xlsxReadContext.readSheetHolder().setCellExtra(cellExtra); xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext); } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java index e153a3b1..6e5246d3 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellFormulaTagHandler.java @@ -1,10 +1,11 @@ package com.alibaba.excel.analysis.v07.handlers; -import org.xml.sax.Attributes; - import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.metadata.data.FormulaData; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; +import org.xml.sax.Attributes; + /** * Cell Handler * @@ -15,14 +16,15 @@ public class CellFormulaTagHandler extends AbstractXlsxTagHandler { @Override public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); - xlsxReadSheetHolder.getTempCellData().setFormula(Boolean.TRUE); xlsxReadSheetHolder.setTempFormula(new StringBuilder()); } @Override public void endElement(XlsxReadContext xlsxReadContext, String name) { XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); - xlsxReadSheetHolder.getTempCellData().setFormulaValue(xlsxReadSheetHolder.getTempFormula().toString()); + FormulaData formulaData = new FormulaData(); + formulaData.setFormulaValue(xlsxReadSheetHolder.getTempFormula().toString()); + xlsxReadSheetHolder.getTempCellData().setFormulaData(formulaData); } @Override diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java index c71b744c..a6fd5340 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellTagHandler.java @@ -6,12 +6,14 @@ import com.alibaba.excel.constant.BuiltinFormats; import com.alibaba.excel.constant.ExcelXmlConstants; import com.alibaba.excel.context.xlsx.XlsxReadContext; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; import com.alibaba.excel.util.BooleanUtils; import com.alibaba.excel.util.PositionUtils; import com.alibaba.excel.util.StringUtils; +import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.xml.sax.Attributes; @@ -30,37 +32,42 @@ public class CellTagHandler extends AbstractXlsxTagHandler { xlsxReadSheetHolder.setColumnIndex(PositionUtils.getCol(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R), xlsxReadSheetHolder.getColumnIndex())); - // t="s" ,it's means String - // t="str" ,it's means String,but does not need to be read in the 'sharedStrings.xml' - // t="inlineStr" ,it's means String - // t="b" ,it's means Boolean - // t="e" ,it's means Error - // t="n" ,it's means Number - // t is null ,it's means Empty or Number + // t="s" ,it means String + // t="str" ,it means String,but does not need to be read in the 'sharedStrings.xml' + // t="inlineStr" ,it means String,but does not need to be read in the 'sharedStrings.xml' + // t="b" ,it means Boolean + // t="e" ,it means Error + // t="n" ,it means Number + // t is null ,it means Empty or Number CellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_T)); - xlsxReadSheetHolder.setTempCellData(new CellData(type)); + xlsxReadSheetHolder.setTempCellData(new ReadCellData<>(type)); xlsxReadSheetHolder.setTempData(new StringBuilder()); // Put in data transformation information String dateFormatIndex = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_S); - Integer dateFormatIndexInteger; + int dateFormatIndexInteger; if (StringUtils.isEmpty(dateFormatIndex)) { dateFormatIndexInteger = DEFAULT_FORMAT_INDEX; } else { dateFormatIndexInteger = Integer.parseInt(dateFormatIndex); } - XSSFCellStyle xssfCellStyle = - xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable().getStyleAt(dateFormatIndexInteger); - int dataFormat = xssfCellStyle.getDataFormat(); - xlsxReadSheetHolder.getTempCellData().setDataFormat(dataFormat); - xlsxReadSheetHolder.getTempCellData().setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat, + StylesTable stylesTable = xlsxReadContext.xlsxReadWorkbookHolder().getStylesTable(); + if (stylesTable == null) { + return; + } + XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(dateFormatIndexInteger); + short dataFormat = xssfCellStyle.getDataFormat(); + DataFormatData dataFormatData = new DataFormatData(); + dataFormatData.setIndex(dataFormat); + dataFormatData.setFormat(BuiltinFormats.getBuiltinFormat(dataFormat, xssfCellStyle.getDataFormatString(), xlsxReadSheetHolder.getGlobalConfiguration().getLocale())); + xlsxReadSheetHolder.getTempCellData().setDataFormatData(dataFormatData); } @Override public void endElement(XlsxReadContext xlsxReadContext, String name) { XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); - CellData tempCellData = xlsxReadSheetHolder.getTempCellData(); + ReadCellData tempCellData = xlsxReadSheetHolder.getTempCellData(); StringBuilder tempData = xlsxReadSheetHolder.getTempData(); String tempDataString = tempData.toString(); CellDataTypeEnum oldType = tempCellData.getType(); @@ -101,7 +108,7 @@ public class CellTagHandler extends AbstractXlsxTagHandler { if (tempCellData.getStringValue() != null && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) { - tempCellData.setStringValue(tempCellData.getStringValue()); + tempCellData.setStringValue(tempCellData.getStringValue().trim()); } tempCellData.checkEmpty(); diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java index 823bafb3..f19794b2 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CountTagHandler.java @@ -1,9 +1,10 @@ package com.alibaba.excel.analysis.v07.handlers; -import org.xml.sax.Attributes; - import com.alibaba.excel.constant.ExcelXmlConstants; import com.alibaba.excel.context.xlsx.XlsxReadContext; +import com.alibaba.excel.util.PositionUtils; + +import org.xml.sax.Attributes; /** * Cell Handler @@ -15,9 +16,8 @@ public class CountTagHandler extends AbstractXlsxTagHandler { @Override public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) { String d = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_REF); - String totalStr = d.substring(d.indexOf(":") + 1, d.length()); - String c = totalStr.toUpperCase().replaceAll("[A-Z]", ""); - xlsxReadContext.readSheetHolder().setApproximateTotalRowNumber(Integer.parseInt(c)); + String totalStr = d.substring(d.indexOf(":") + 1); + xlsxReadContext.readSheetHolder().setApproximateTotalRowNumber(PositionUtils.getRow(totalStr) + 1); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java index 877c6a5f..37965254 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java @@ -2,17 +2,17 @@ package com.alibaba.excel.analysis.v07.handlers; import java.util.LinkedHashMap; -import org.xml.sax.Attributes; - import com.alibaba.excel.constant.ExcelXmlConstants; import com.alibaba.excel.context.xlsx.XlsxReadContext; import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.metadata.Cell; import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; -import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.PositionUtils; +import org.apache.commons.collections4.MapUtils; +import org.xml.sax.Attributes; + /** * Cell Handler * @@ -40,13 +40,12 @@ public class RowTagHandler extends AbstractXlsxTagHandler { @Override public void endElement(XlsxReadContext xlsxReadContext, String name) { XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder(); - RowTypeEnum rowType = - CollectionUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA; + RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA; xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType, xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap())); xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext); xlsxReadSheetHolder.setColumnIndex(null); - xlsxReadSheetHolder.setCellMap(new LinkedHashMap()); + xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>()); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java index 65eaa6a9..869ef3cb 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/XlsxRowHandler.java @@ -3,10 +3,6 @@ package com.alibaba.excel.analysis.v07.handlers.sax; import java.util.HashMap; import java.util.Map; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - import com.alibaba.excel.analysis.v07.handlers.CellFormulaTagHandler; import com.alibaba.excel.analysis.v07.handlers.CellInlineStringValueTagHandler; import com.alibaba.excel.analysis.v07.handlers.CellTagHandler; @@ -19,9 +15,15 @@ import com.alibaba.excel.analysis.v07.handlers.XlsxTagHandler; import com.alibaba.excel.constant.ExcelXmlConstants; import com.alibaba.excel.context.xlsx.XlsxReadContext; +import lombok.extern.slf4j.Slf4j; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + /** * @author jipengfei */ +@Slf4j public class XlsxRowHandler extends DefaultHandler { private XlsxReadContext xlsxReadContext; private static final Map XLSX_CELL_HANDLER_MAP = new HashMap(32); diff --git a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java index 5c778a84..e763ab37 100644 --- a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java +++ b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java @@ -23,7 +23,7 @@ public @interface ExcelProperty { *

* write: It automatically merges when you have more than one head *

- * read: When you have multiple heads, take the first one + * read: When you have multiple heads, take the last one * * @return The name of the sheet header */ @@ -32,7 +32,7 @@ public @interface ExcelProperty { /** * Index of column * - * Read or write it on the index of column,If it's equal to -1, it's sorted by Java class. + * Read or write it on the index of column, If it's equal to -1, it's sorted by Java class. * * priority: index > order > default sort * diff --git a/src/main/java/com/alibaba/excel/annotation/write/style/ContentFontStyle.java b/src/main/java/com/alibaba/excel/annotation/write/style/ContentFontStyle.java index d593aef3..533ae6aa 100644 --- a/src/main/java/com/alibaba/excel/annotation/write/style/ContentFontStyle.java +++ b/src/main/java/com/alibaba/excel/annotation/write/style/ContentFontStyle.java @@ -52,7 +52,7 @@ public @interface ContentFontStyle { short color() default -1; /** - * Set normal,super or subscript. + * Set normal, super or subscript. * * @see Font#SS_NONE * @see Font#SS_SUPER diff --git a/src/main/java/com/alibaba/excel/annotation/write/style/HeadFontStyle.java b/src/main/java/com/alibaba/excel/annotation/write/style/HeadFontStyle.java index 957e50f5..d25dad77 100644 --- a/src/main/java/com/alibaba/excel/annotation/write/style/HeadFontStyle.java +++ b/src/main/java/com/alibaba/excel/annotation/write/style/HeadFontStyle.java @@ -52,7 +52,7 @@ public @interface HeadFontStyle { short color() default -1; /** - * Set normal,super or subscript. + * Set normal, super or subscript. * * @see Font#SS_NONE * @see Font#SS_SUPER diff --git a/src/main/java/com/alibaba/excel/annotation/write/style/HeadStyle.java b/src/main/java/com/alibaba/excel/annotation/write/style/HeadStyle.java index d882da8f..5bc3ffc6 100644 --- a/src/main/java/com/alibaba/excel/annotation/write/style/HeadStyle.java +++ b/src/main/java/com/alibaba/excel/annotation/write/style/HeadStyle.java @@ -53,7 +53,6 @@ public @interface HeadStyle { /** * Set whether the text should be wrapped. Setting this flag to true make all content visible within a * cell by displaying it on multiple lines - * */ boolean wrapped() default true; @@ -108,7 +107,6 @@ public @interface HeadStyle { * Set the color to use for the right border * * @see IndexedColors - * */ short rightBorderColor() default -1; @@ -116,7 +114,6 @@ public @interface HeadStyle { * Set the color to use for the top border * * @see IndexedColors - * */ short topBorderColor() default -1; @@ -124,7 +121,6 @@ public @interface HeadStyle { * Set the color to use for the bottom border * * @see IndexedColors - * */ short bottomBorderColor() default -1; @@ -139,7 +135,6 @@ public @interface HeadStyle { * Set the background fill color. * * @see IndexedColors - * */ short fillBackgroundColor() default -1; @@ -147,7 +142,6 @@ public @interface HeadStyle { * Set the foreground fill color Note: Ensure Foreground color is set prior to background color. * * @see IndexedColors - * */ short fillForegroundColor() default -1; diff --git a/src/main/java/com/alibaba/excel/cache/Ehcache.java b/src/main/java/com/alibaba/excel/cache/Ehcache.java index 4e757fcd..a5250900 100644 --- a/src/main/java/com/alibaba/excel/cache/Ehcache.java +++ b/src/main/java/com/alibaba/excel/cache/Ehcache.java @@ -1,50 +1,49 @@ package com.alibaba.excel.cache; import java.io.File; -import java.util.HashMap; +import java.util.ArrayList; import java.util.UUID; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.util.FileUtils; +import com.alibaba.excel.util.ListUtils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.ehcache.CacheManager; import org.ehcache.config.CacheConfiguration; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.CacheManagerBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.util.CollectionUtils; -import com.alibaba.excel.util.FileUtils; /** * Default cache * * @author Jiaju Zhuang */ +@Slf4j public class Ehcache implements ReadCache { - - private static final Logger LOGGER = LoggerFactory.getLogger(Ehcache.class); - private static final int BATCH_COUNT = 1000; - private static final int DEBUG_WRITE_SIZE = 100 * 10000; - private static final int DEBUG_CACHE_MISS_SIZE = 1000; + public static final int BATCH_COUNT = 1000; /** * Key index */ - private int index = 0; - private HashMap dataMap = new HashMap(BATCH_COUNT * 4 / 3 + 1); - private static CacheManager fileCacheManager; - private static CacheConfiguration fileCacheConfiguration; - private static CacheManager activeCacheManager; - private CacheConfiguration activeCacheConfiguration; + private int activeIndex = 0; + public static final int DEBUG_CACHE_MISS_SIZE = 1000; + public static final int DEBUG_WRITE_SIZE = 100 * 10000; + private ArrayList dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + private static final CacheManager FILE_CACHE_MANAGER; + private static final CacheConfiguration FILE_CACHE_CONFIGURATION; + private static final CacheManager ACTIVE_CACHE_MANAGER; + private final CacheConfiguration activeCacheConfiguration; /** * Bulk storage data */ - private org.ehcache.Cache fileCache; + private org.ehcache.Cache fileCache; /** * Currently active cache */ - private org.ehcache.Cache activeCache; + private org.ehcache.Cache activeCache; private String cacheAlias; /** * Count the number of cache misses @@ -53,7 +52,7 @@ public class Ehcache implements ReadCache { public Ehcache(int maxCacheActivateSize) { activeCacheConfiguration = CacheConfigurationBuilder - .newCacheConfigurationBuilder(Integer.class, HashMap.class, + .newCacheConfigurationBuilder(Integer.class, ArrayList.class, ResourcePoolsBuilder.newResourcePoolsBuilder().heap(maxCacheActivateSize, MemoryUnit.MB)) .withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(maxCacheActivateSize, MemoryUnit.MB) .build(); @@ -61,11 +60,11 @@ public class Ehcache implements ReadCache { static { File cacheFile = FileUtils.createCacheTmpFile(); - fileCacheManager = + FILE_CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(cacheFile)).build(true); - activeCacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true); - fileCacheConfiguration = CacheConfigurationBuilder - .newCacheConfigurationBuilder(Integer.class, HashMap.class, + ACTIVE_CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder().build(true); + FILE_CACHE_CONFIGURATION = CacheConfigurationBuilder + .newCacheConfigurationBuilder(Integer.class, ArrayList.class, ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.GB)) .withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(10, MemoryUnit.GB).build(); } @@ -73,21 +72,22 @@ public class Ehcache implements ReadCache { @Override public void init(AnalysisContext analysisContext) { cacheAlias = UUID.randomUUID().toString(); - fileCache = fileCacheManager.createCache(cacheAlias, fileCacheConfiguration); - activeCache = activeCacheManager.createCache(cacheAlias, activeCacheConfiguration); + fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION); + activeCache = ACTIVE_CACHE_MANAGER.createCache(cacheAlias, activeCacheConfiguration); } @Override public void put(String value) { - dataMap.put(index, value); - if ((index + 1) % BATCH_COUNT == 0) { - fileCache.put(index / BATCH_COUNT, dataMap); - dataMap = new HashMap(BATCH_COUNT * 4 / 3 + 1); + dataList.add(value); + if (dataList.size() >= BATCH_COUNT) { + fileCache.put(activeIndex, dataList); + activeIndex++; + dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } - index++; - if (LOGGER.isDebugEnabled()) { - if (index % DEBUG_WRITE_SIZE == 0) { - LOGGER.debug("Already put :{}", index); + if (log.isDebugEnabled()) { + int alreadyPut = activeIndex * BATCH_COUNT + dataList.size(); + if (alreadyPut % DEBUG_WRITE_SIZE == 0) { + log.debug("Already put :{}", alreadyPut); } } } @@ -98,31 +98,31 @@ public class Ehcache implements ReadCache { return null; } int route = key / BATCH_COUNT; - HashMap dataMap = activeCache.get(route); - if (dataMap == null) { - dataMap = fileCache.get(route); - activeCache.put(route, dataMap); - if (LOGGER.isDebugEnabled()) { + ArrayList dataList = activeCache.get(route); + if (dataList == null) { + dataList = fileCache.get(route); + activeCache.put(route, dataList); + if (log.isDebugEnabled()) { if (cacheMiss++ % DEBUG_CACHE_MISS_SIZE == 0) { - LOGGER.debug("Cache misses count:{}", cacheMiss); + log.debug("Cache misses count:{}", cacheMiss); } } } - return dataMap.get(key); + return dataList.get(key % BATCH_COUNT); } @Override public void putFinished() { - if (CollectionUtils.isEmpty(dataMap)) { + if (CollectionUtils.isEmpty(dataList)) { return; } - fileCache.put(index / BATCH_COUNT, dataMap); + fileCache.put(activeIndex, dataList); } @Override public void destroy() { - fileCacheManager.removeCache(cacheAlias); - activeCacheManager.removeCache(cacheAlias); + FILE_CACHE_MANAGER.removeCache(cacheAlias); + ACTIVE_CACHE_MANAGER.removeCache(cacheAlias); } } diff --git a/src/main/java/com/alibaba/excel/cache/MapCache.java b/src/main/java/com/alibaba/excel/cache/MapCache.java index ae948fbc..f83a1233 100644 --- a/src/main/java/com/alibaba/excel/cache/MapCache.java +++ b/src/main/java/com/alibaba/excel/cache/MapCache.java @@ -1,26 +1,24 @@ package com.alibaba.excel.cache; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import com.alibaba.excel.context.AnalysisContext; /** - * * Putting temporary data directly into a map is a little more efficient but very memory intensive * * @author Jiaju Zhuang */ public class MapCache implements ReadCache { - private Map cache = new HashMap(); - private int index = 0; + private List cache = new ArrayList<>(); @Override public void init(AnalysisContext analysisContext) {} @Override public void put(String value) { - cache.put(index++, value); + cache.add(value); } @Override diff --git a/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java b/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java index 95eb0b8f..ec7d5c9a 100644 --- a/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java +++ b/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java @@ -1,6 +1,9 @@ package com.alibaba.excel.constant; import java.util.Locale; +import java.util.Map; + +import com.alibaba.excel.util.MapUtils; /** * Excel's built-in format conversion.Currently only supports Chinese. @@ -17,7 +20,9 @@ import java.util.Locale; **/ public class BuiltinFormats { - private static final String[] BUILTIN_FORMATS_CN = { + public static short GENERAL = 0; + + public static final String[] BUILTIN_FORMATS_CN = { // 0 "General", // 1 @@ -189,7 +194,7 @@ public class BuiltinFormats { // end }; - private static final String[] BUILTIN_FORMATS_US = { + public static final String[] BUILTIN_FORMATS_US = { // 0 "General", // 1 @@ -361,7 +366,11 @@ public class BuiltinFormats { // end }; - public static String getBuiltinFormat(Integer index, String defaultFormat, Locale locale) { + public static final Map BUILTIN_FORMATS_MAP_CN = buildMap(BUILTIN_FORMATS_CN); + public static final Map BUILTIN_FORMATS_MAP_US = buildMap(BUILTIN_FORMATS_US); + public static final short MIN_CUSTOM_DATA_FORMAT_INDEX = 82; + + public static String getBuiltinFormat(Short index, String defaultFormat, Locale locale) { String[] builtinFormat = switchBuiltinFormats(locale); if (index == null || index < 0 || index >= builtinFormat.length) { return defaultFormat; @@ -369,11 +378,26 @@ public class BuiltinFormats { return builtinFormat[index]; } - private static String[] switchBuiltinFormats(Locale locale) { + public static String[] switchBuiltinFormats(Locale locale) { if (locale != null && Locale.US.getCountry().equals(locale.getCountry())) { return BUILTIN_FORMATS_US; } return BUILTIN_FORMATS_CN; } + public static Map switchBuiltinFormatsMap(Locale locale) { + if (locale != null && Locale.US.getCountry().equals(locale.getCountry())) { + return BUILTIN_FORMATS_MAP_US; + } + return BUILTIN_FORMATS_MAP_CN; + } + + private static Map buildMap(String[] builtinFormats) { + Map map = MapUtils.newHashMapWithExpectedSize(builtinFormats.length); + for (int i = 0; i < builtinFormats.length; i++) { + map.put(builtinFormats[i], (short)i); + } + return map; + } + } diff --git a/src/main/java/com/alibaba/excel/constant/OrderConstant.java b/src/main/java/com/alibaba/excel/constant/OrderConstant.java new file mode 100644 index 00000000..54d438e5 --- /dev/null +++ b/src/main/java/com/alibaba/excel/constant/OrderConstant.java @@ -0,0 +1,24 @@ +package com.alibaba.excel.constant; + +/** + * Order constant. + * + * @author Jiaju Zhuang + */ +public class OrderConstant { + + /** + * Define style. + */ + public static final int DEFINE_STYLE = -50000; + + /** + * default order. + */ + public static final int DEFAULT_ORDER = 0; + + /** + * Sorting of styles written to cells. + */ + public static final int FILL_STYLE = 50000; +} diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContext.java b/src/main/java/com/alibaba/excel/context/AnalysisContext.java index df17f55d..37039cbc 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContext.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContext.java @@ -4,7 +4,6 @@ import java.io.InputStream; import java.util.List; import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.holder.ReadHolder; import com.alibaba.excel.read.metadata.holder.ReadRowHolder; @@ -92,15 +91,6 @@ public interface AnalysisContext { */ void readSheetList(List readSheetList); - /** - * get current sheet - * - * @return current analysis sheet - * @deprecated please use {@link #readSheetHolder()} - */ - @Deprecated - Sheet getCurrentSheet(); - /** * * get excel type diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java index ab27e87e..4edaef37 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java @@ -3,17 +3,15 @@ package com.alibaba.excel.context; import java.io.InputStream; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.exception.ExcelAnalysisException; -import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.holder.ReadHolder; import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; @@ -22,12 +20,13 @@ import com.alibaba.excel.read.processor.AnalysisEventProcessor; import com.alibaba.excel.read.processor.DefaultAnalysisEventProcessor; import com.alibaba.excel.support.ExcelTypeEnum; +import lombok.extern.slf4j.Slf4j; + /** - * * @author jipengfei */ +@Slf4j public class AnalysisContextImpl implements AnalysisContext { - private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisContextImpl.class); /** * The Workbook currently written */ @@ -60,13 +59,16 @@ public class AnalysisContextImpl implements AnalysisContext { case XLSX: readWorkbookHolder = new XlsxReadWorkbookHolder(readWorkbook); break; + case CSV: + readWorkbookHolder = new CsvReadWorkbookHolder(readWorkbook); + break; default: break; } currentReadHolder = readWorkbookHolder; analysisEventProcessor = new DefaultAnalysisEventProcessor(); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Initialization 'AnalysisContextImpl' complete"); + if (log.isDebugEnabled()) { + log.debug("Initialization 'AnalysisContextImpl' complete"); } } @@ -79,6 +81,9 @@ public class AnalysisContextImpl implements AnalysisContext { case XLSX: readSheetHolder = new XlsxReadSheetHolder(readSheet, readWorkbookHolder); break; + case CSV: + readSheetHolder = new CsvReadSheetHolder(readSheet, readWorkbookHolder); + break; default: break; } @@ -87,8 +92,8 @@ public class AnalysisContextImpl implements AnalysisContext { throw new ExcelAnalysisException("Cannot read sheet repeatedly."); } readWorkbookHolder.getHasReadSheet().add(readSheetHolder.getSheetNo()); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Began to read:{}", readSheetHolder); + if (log.isDebugEnabled()) { + log.debug("Began to read:{}", readSheetHolder); } } @@ -137,16 +142,6 @@ public class AnalysisContextImpl implements AnalysisContext { } - @Override - public Sheet getCurrentSheet() { - Sheet sheet = new Sheet(readSheetHolder.getSheetNo() + 1); - sheet.setSheetName(readSheetHolder.getSheetName()); - sheet.setHead(readSheetHolder.getHead()); - sheet.setClazz(readSheetHolder.getClazz()); - sheet.setHeadLineMun(readSheetHolder.getHeadRowNumber()); - return sheet; - } - @Override public ExcelTypeEnum getExcelType() { return readWorkbookHolder.getExcelType(); diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index c1f89f02..2c66b535 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -6,26 +6,10 @@ import java.io.OutputStream; import java.util.Map; import java.util.UUID; -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackageAccess; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.EncryptionMode; -import org.apache.poi.poifs.crypt.Encryptor; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.enums.WriteTypeEnum; import com.alibaba.excel.exception.ExcelGenerateException; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.FileUtils; @@ -42,6 +26,22 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import com.alibaba.excel.write.property.ExcelWriteHeadProperty; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionMode; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * A context is the main anchorage point of a excel writer. * @@ -50,6 +50,7 @@ import com.alibaba.excel.write.property.ExcelWriteHeadProperty; public class WriteContextImpl implements WriteContext { private static final Logger LOGGER = LoggerFactory.getLogger(WriteContextImpl.class); + private static final String NO_SHEETS = "no sheets"; /** * The Workbook currently written @@ -138,7 +139,7 @@ public class WriteContextImpl implements WriteContext { return false; } if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Sheet:{} is already existed", writeSheet.getSheetNo()); + LOGGER.debug("Sheet:{},{} is already existed", writeSheet.getSheetNo(), writeSheet.getSheetName()); } writeSheetHolder.setNewInitialization(Boolean.FALSE); writeTableHolder = null; @@ -178,8 +179,12 @@ public class WriteContextImpl implements WriteContext { writeSheetHolder .setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheet(writeSheetHolder.getSheetName())); } - } catch (Exception e) { - currentSheet = createSheet(); + } catch (IllegalArgumentException e) { + if (e.getMessage() != null && e.getMessage().contains(NO_SHEETS)) { + currentSheet = createSheet(); + } else { + throw e; + } } if (currentSheet == null) { currentSheet = createSheet(); @@ -240,10 +245,16 @@ public class WriteContextImpl implements WriteContext { Head head = entry.getValue(); int columnIndex = entry.getKey(); WriteHandlerUtils.beforeCellCreate(this, row, head, columnIndex, relativeRowIndex, Boolean.TRUE); + Cell cell = row.createCell(columnIndex); + WriteHandlerUtils.afterCellCreate(this, cell, head, relativeRowIndex, Boolean.TRUE); - cell.setCellValue(head.getHeadNameList().get(relativeRowIndex)); - WriteHandlerUtils.afterCellDispose(this, (CellData) null, cell, head, relativeRowIndex, Boolean.TRUE); + + WriteCellData writeCellData = new WriteCellData<>(head.getHeadNameList().get(relativeRowIndex)); + cell.setCellValue(writeCellData.getStringValue()); + + WriteHandlerUtils.afterCellDispose(this, writeCellData, cell, head, relativeRowIndex, + Boolean.TRUE); } } @@ -280,7 +291,7 @@ public class WriteContextImpl implements WriteContext { } private void initCurrentTableHolder(WriteTable writeTable) { - writeTableHolder = new WriteTableHolder(writeTable, writeSheetHolder, writeWorkbookHolder); + writeTableHolder = new WriteTableHolder(writeTable, writeSheetHolder); writeSheetHolder.getHasBeenInitializedTable().put(writeTable.getTableNo(), writeTableHolder); currentWriteHolder = writeTableHolder; if (LOGGER.isDebugEnabled()) { @@ -346,7 +357,7 @@ public class WriteContextImpl implements WriteContext { try { Workbook workbook = writeWorkbookHolder.getWorkbook(); if (workbook instanceof SXSSFWorkbook) { - ((SXSSFWorkbook) workbook).dispose(); + ((SXSSFWorkbook)workbook).dispose(); } } catch (Throwable t) { throwable = t; @@ -426,7 +437,7 @@ public class WriteContextImpl implements WriteContext { if (writeWorkbookHolder.getFile() != null) { return false; } - File tempXlsx = FileUtils.createTmpFile(UUID.randomUUID().toString() + ".xlsx"); + File tempXlsx = FileUtils.createTmpFile(UUID.randomUUID() + ".xlsx"); FileOutputStream tempFileOutputStream = new FileOutputStream(tempXlsx); try { writeWorkbookHolder.getWorkbook().write(tempFileOutputStream); @@ -441,14 +452,9 @@ public class WriteContextImpl implements WriteContext { throw e; } } - POIFSFileSystem fileSystem = null; - try { - fileSystem = openFileSystemAndEncrypt(tempXlsx); + try (POIFSFileSystem fileSystem = openFileSystemAndEncrypt(tempXlsx)) { fileSystem.writeFilesystem(writeWorkbookHolder.getOutputStream()); } finally { - if (fileSystem != null) { - fileSystem.close(); - } if (!tempXlsx.delete()) { throw new ExcelGenerateException("Can not delete temp File!"); } @@ -467,19 +473,9 @@ public class WriteContextImpl implements WriteContext { if (writeWorkbookHolder.getFile() == null) { return; } - FileOutputStream fileOutputStream = null; - POIFSFileSystem fileSystem = null; - try { - fileSystem = openFileSystemAndEncrypt(writeWorkbookHolder.getFile()); - fileOutputStream = new FileOutputStream(writeWorkbookHolder.getFile()); + try (POIFSFileSystem fileSystem = openFileSystemAndEncrypt(writeWorkbookHolder.getFile()); + FileOutputStream fileOutputStream = new FileOutputStream(writeWorkbookHolder.getFile())) { fileSystem.writeFilesystem(fileOutputStream); - } finally { - if (fileOutputStream != null) { - fileOutputStream.close(); - } - if (fileSystem != null) { - fileSystem.close(); - } } } @@ -487,15 +483,9 @@ public class WriteContextImpl implements WriteContext { POIFSFileSystem fileSystem = new POIFSFileSystem(); Encryptor encryptor = new EncryptionInfo(EncryptionMode.standard).getEncryptor(); encryptor.confirmPassword(writeWorkbookHolder.getPassword()); - OPCPackage opcPackage = null; - try { - opcPackage = OPCPackage.open(file, PackageAccess.READ_WRITE); - OutputStream outputStream = encryptor.getDataStream(fileSystem); + try (OPCPackage opcPackage = OPCPackage.open(file, PackageAccess.READ_WRITE); + OutputStream outputStream = encryptor.getDataStream(fileSystem)) { opcPackage.save(outputStream); - } finally { - if (opcPackage != null) { - opcPackage.close(); - } } return fileSystem; } diff --git a/src/main/java/com/alibaba/excel/context/csv/CsvReadContext.java b/src/main/java/com/alibaba/excel/context/csv/CsvReadContext.java new file mode 100644 index 00000000..00bcd54a --- /dev/null +++ b/src/main/java/com/alibaba/excel/context/csv/CsvReadContext.java @@ -0,0 +1,26 @@ +package com.alibaba.excel.context.csv; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; + +/** + * A context is the main anchorage point of a ls xls reader. + * + * @author Jiaju Zhuang + **/ +public interface CsvReadContext extends AnalysisContext { + /** + * All information about the workbook you are currently working on. + * + * @return Current workbook holder + */ + CsvReadWorkbookHolder csvReadWorkbookHolder(); + + /** + * All information about the sheet you are currently working on. + * + * @return Current sheet holder + */ + CsvReadSheetHolder csvReadSheetHolder(); +} diff --git a/src/main/java/com/alibaba/excel/context/csv/DefaultCsvReadContext.java b/src/main/java/com/alibaba/excel/context/csv/DefaultCsvReadContext.java new file mode 100644 index 00000000..d8653a88 --- /dev/null +++ b/src/main/java/com/alibaba/excel/context/csv/DefaultCsvReadContext.java @@ -0,0 +1,29 @@ +package com.alibaba.excel.context.csv; + +import com.alibaba.excel.context.AnalysisContextImpl; +import com.alibaba.excel.read.metadata.ReadWorkbook; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; +import com.alibaba.excel.support.ExcelTypeEnum; + +/** + * A context is the main anchorage point of a ls xls reader. + * + * @author Jiaju Zhuang + */ +public class DefaultCsvReadContext extends AnalysisContextImpl implements CsvReadContext { + + public DefaultCsvReadContext(ReadWorkbook readWorkbook, ExcelTypeEnum actualExcelType) { + super(readWorkbook, actualExcelType); + } + + @Override + public CsvReadWorkbookHolder csvReadWorkbookHolder() { + return (CsvReadWorkbookHolder)readWorkbookHolder(); + } + + @Override + public CsvReadSheetHolder csvReadSheetHolder() { + return (CsvReadSheetHolder)readSheetHolder(); + } +} diff --git a/src/main/java/com/alibaba/excel/converters/AutoConverter.java b/src/main/java/com/alibaba/excel/converters/AutoConverter.java index 800d2d85..5981e7ac 100644 --- a/src/main/java/com/alibaba/excel/converters/AutoConverter.java +++ b/src/main/java/com/alibaba/excel/converters/AutoConverter.java @@ -1,36 +1,9 @@ package com.alibaba.excel.converters; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.metadata.property.ExcelContentProperty; - /** * An empty converter.It's automatically converted by type. * * @author Jiaju Zhuang */ -public class AutoConverter implements Converter { - - @Override - public Class supportJavaTypeKey() { - return null; - } - - @Override - public CellDataTypeEnum supportExcelTypeKey() { - return null; - } - - @Override - public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - return null; - } - - @Override - public CellData convertToExcelData(Object value, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - return null; - } +public class AutoConverter implements Converter { } diff --git a/src/main/java/com/alibaba/excel/converters/Converter.java b/src/main/java/com/alibaba/excel/converters/Converter.java index 8700d127..df7f4719 100644 --- a/src/main/java/com/alibaba/excel/converters/Converter.java +++ b/src/main/java/com/alibaba/excel/converters/Converter.java @@ -1,15 +1,16 @@ package com.alibaba.excel.converters; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** * Convert between Java objects and excel objects * - * @author Dan Zheng * @param + * @author Dan Zheng */ public interface Converter { @@ -18,44 +19,68 @@ public interface Converter { * * @return Support for Java class */ - Class supportJavaTypeKey(); + default Class supportJavaTypeKey() { + throw new UnsupportedOperationException("The current operation is not supported by the current converter."); + } /** * Back to object enum in excel * * @return Support for {@link CellDataTypeEnum} */ - CellDataTypeEnum supportExcelTypeKey(); + default CellDataTypeEnum supportExcelTypeKey() { + throw new UnsupportedOperationException("The current operation is not supported by the current converter."); + } + + /** + * Convert excel objects to Java objects + * + * @param cellData Excel cell data.NotNull. + * @param contentProperty Content property.Nullable. + * @param globalConfiguration Global configuration.NotNull. + * @return Data to put into a Java object + * @throws Exception Exception. + */ + default T convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + throw new UnsupportedOperationException("The current operation is not supported by the current converter."); + } /** * Convert excel objects to Java objects * - * @param cellData - * Excel cell data.NotNull. - * @param contentProperty - * Content property.Nullable. - * @param globalConfiguration - * Global configuration.NotNull. + * @param context read converter context * @return Data to put into a Java object - * @throws Exception - * Exception. + * @throws Exception Exception. + */ + default T convertToJavaData(ReadConverterContext context) throws Exception { + return convertToJavaData(context.getReadCellData(), context.getContentProperty(), + context.getAnalysisContext().currentReadHolder().globalConfiguration()); + } + + /** + * Convert Java objects to excel objects + * + * @param value Java Data.NotNull. + * @param contentProperty Content property.Nullable. + * @param globalConfiguration Global configuration.NotNull. + * @return Data to put into a Excel + * @throws Exception Exception. */ - T convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) throws Exception; + default WriteCellData convertToExcelData(T value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + throw new UnsupportedOperationException("The current operation is not supported by the current converter."); + } /** * Convert Java objects to excel objects * - * @param value - * Java Data.NotNull. - * @param contentProperty - * Content property.Nullable. - * @param globalConfiguration - * Global configuration.NotNull. + * @param context write context * @return Data to put into a Excel - * @throws Exception - * Exception. + * @throws Exception Exception. */ - CellData convertToExcelData(T value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) - throws Exception; + default WriteCellData convertToExcelData(WriteConverterContext context) throws Exception { + return convertToExcelData(context.getValue(), context.getContentProperty(), + context.getWriteContext().currentWriteHolder().globalConfiguration()); + } } diff --git a/src/main/java/com/alibaba/excel/converters/ConverterKeyBuild.java b/src/main/java/com/alibaba/excel/converters/ConverterKeyBuild.java index 0bd54991..f1068591 100644 --- a/src/main/java/com/alibaba/excel/converters/ConverterKeyBuild.java +++ b/src/main/java/com/alibaba/excel/converters/ConverterKeyBuild.java @@ -1,9 +1,9 @@ package com.alibaba.excel.converters; -import java.util.HashMap; import java.util.Map; import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.util.MapUtils; /** * Converter unique key.Consider that you can just use class as the key. @@ -12,7 +12,7 @@ import com.alibaba.excel.enums.CellDataTypeEnum; */ public class ConverterKeyBuild { - private static final Map BOXING_MAP = new HashMap(16); + private static final Map BOXING_MAP = MapUtils.newHashMap(); static { BOXING_MAP.put(int.class.getName(), Integer.class.getName()); @@ -25,7 +25,7 @@ public class ConverterKeyBuild { BOXING_MAP.put(boolean.class.getName(), Boolean.class.getName()); } - public static String buildKey(Class clazz) { + public static String buildKey(Class clazz) { String className = clazz.getName(); String boxingClassName = BOXING_MAP.get(clazz.getName()); if (boxingClassName == null) { @@ -34,7 +34,11 @@ public class ConverterKeyBuild { return boxingClassName; } - public static String buildKey(Class clazz, CellDataTypeEnum cellDataTypeEnum) { - return buildKey(clazz) + "-" + cellDataTypeEnum.toString(); + public static String buildKey(Class clazz, CellDataTypeEnum cellDataTypeEnum) { + String key = buildKey(clazz); + if (cellDataTypeEnum == null) { + return key; + } + return key + "-" + cellDataTypeEnum; } } diff --git a/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java b/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java index 01822559..fda84b84 100644 --- a/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java +++ b/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java @@ -1,11 +1,13 @@ package com.alibaba.excel.converters; -import java.util.HashMap; import java.util.Map; import com.alibaba.excel.converters.bigdecimal.BigDecimalBooleanConverter; import com.alibaba.excel.converters.bigdecimal.BigDecimalNumberConverter; import com.alibaba.excel.converters.bigdecimal.BigDecimalStringConverter; +import com.alibaba.excel.converters.biginteger.BigIntegerBooleanConverter; +import com.alibaba.excel.converters.biginteger.BigIntegerNumberConverter; +import com.alibaba.excel.converters.biginteger.BigIntegerStringConverter; import com.alibaba.excel.converters.booleanconverter.BooleanBooleanConverter; import com.alibaba.excel.converters.booleanconverter.BooleanNumberConverter; import com.alibaba.excel.converters.booleanconverter.BooleanStringConverter; @@ -14,6 +16,7 @@ import com.alibaba.excel.converters.bytearray.ByteArrayImageConverter; import com.alibaba.excel.converters.byteconverter.ByteBooleanConverter; import com.alibaba.excel.converters.byteconverter.ByteNumberConverter; import com.alibaba.excel.converters.byteconverter.ByteStringConverter; +import com.alibaba.excel.converters.date.DateDateConverter; import com.alibaba.excel.converters.date.DateNumberConverter; import com.alibaba.excel.converters.date.DateStringConverter; import com.alibaba.excel.converters.doubleconverter.DoubleBooleanConverter; @@ -27,6 +30,9 @@ import com.alibaba.excel.converters.inputstream.InputStreamImageConverter; import com.alibaba.excel.converters.integer.IntegerBooleanConverter; import com.alibaba.excel.converters.integer.IntegerNumberConverter; import com.alibaba.excel.converters.integer.IntegerStringConverter; +import com.alibaba.excel.converters.localdatetime.LocalDateNumberConverter; +import com.alibaba.excel.converters.localdatetime.LocalDateTimeDateConverter; +import com.alibaba.excel.converters.localdatetime.LocalDateTimeStringConverter; import com.alibaba.excel.converters.longconverter.LongBooleanConverter; import com.alibaba.excel.converters.longconverter.LongNumberConverter; import com.alibaba.excel.converters.longconverter.LongStringConverter; @@ -38,6 +44,7 @@ import com.alibaba.excel.converters.string.StringErrorConverter; import com.alibaba.excel.converters.string.StringNumberConverter; import com.alibaba.excel.converters.string.StringStringConverter; import com.alibaba.excel.converters.url.UrlImageConverter; +import com.alibaba.excel.util.MapUtils; /** * Load default handler @@ -45,8 +52,8 @@ import com.alibaba.excel.converters.url.UrlImageConverter; * @author Jiaju Zhuang */ public class DefaultConverterLoader { - private static Map defaultWriteConverter; - private static Map allConverter; + private static Map> defaultWriteConverter; + private static Map> allConverter; static { initDefaultWriteConverter(); @@ -54,11 +61,15 @@ public class DefaultConverterLoader { } private static void initAllConverter() { - allConverter = new HashMap(64); + allConverter = MapUtils.newHashMapWithExpectedSize(40); putAllConverter(new BigDecimalBooleanConverter()); putAllConverter(new BigDecimalNumberConverter()); putAllConverter(new BigDecimalStringConverter()); + putAllConverter(new BigIntegerBooleanConverter()); + putAllConverter(new BigIntegerNumberConverter()); + putAllConverter(new BigIntegerStringConverter()); + putAllConverter(new BooleanBooleanConverter()); putAllConverter(new BooleanNumberConverter()); putAllConverter(new BooleanStringConverter()); @@ -70,6 +81,9 @@ public class DefaultConverterLoader { putAllConverter(new DateNumberConverter()); putAllConverter(new DateStringConverter()); + putAllConverter(new LocalDateNumberConverter()); + putAllConverter(new LocalDateTimeStringConverter()); + putAllConverter(new DoubleBooleanConverter()); putAllConverter(new DoubleNumberConverter()); putAllConverter(new DoubleStringConverter()); @@ -94,14 +108,18 @@ public class DefaultConverterLoader { putAllConverter(new StringNumberConverter()); putAllConverter(new StringStringConverter()); putAllConverter(new StringErrorConverter()); + + putAllConverter(new BigIntegerStringConverter()); } private static void initDefaultWriteConverter() { - defaultWriteConverter = new HashMap(32); + defaultWriteConverter = MapUtils.newHashMapWithExpectedSize(40); putWriteConverter(new BigDecimalNumberConverter()); + putWriteConverter(new BigIntegerNumberConverter()); putWriteConverter(new BooleanBooleanConverter()); putWriteConverter(new ByteNumberConverter()); - putWriteConverter(new DateStringConverter()); + putWriteConverter(new DateDateConverter()); + putWriteConverter(new LocalDateTimeDateConverter()); putWriteConverter(new DoubleNumberConverter()); putWriteConverter(new FloatNumberConverter()); putWriteConverter(new IntegerNumberConverter()); @@ -113,6 +131,21 @@ public class DefaultConverterLoader { putWriteConverter(new ByteArrayImageConverter()); putWriteConverter(new BoxingByteArrayImageConverter()); putWriteConverter(new UrlImageConverter()); + + // In some cases, it must be converted to string + putWriteStringConverter(new BigDecimalStringConverter()); + putWriteStringConverter(new BigIntegerStringConverter()); + putWriteStringConverter(new BooleanStringConverter()); + putWriteStringConverter(new ByteStringConverter()); + putWriteStringConverter(new DateStringConverter()); + putWriteStringConverter(new LocalDateTimeStringConverter()); + putWriteStringConverter(new DoubleStringConverter()); + putWriteStringConverter(new FloatStringConverter()); + putWriteStringConverter(new IntegerStringConverter()); + putWriteStringConverter(new LongStringConverter()); + putWriteStringConverter(new ShortStringConverter()); + putWriteStringConverter(new StringStringConverter()); + putWriteStringConverter(new BigIntegerStringConverter()); } /** @@ -120,20 +153,25 @@ public class DefaultConverterLoader { * * @return */ - public static Map loadDefaultWriteConverter() { + public static Map> loadDefaultWriteConverter() { return defaultWriteConverter; } - private static void putWriteConverter(Converter converter) { + private static void putWriteConverter(Converter converter) { defaultWriteConverter.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey()), converter); } + private static void putWriteStringConverter(Converter converter) { + defaultWriteConverter.put( + ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()), converter); + } + /** * Load default read converter * * @return */ - public static Map loadDefaultReadConverter() { + public static Map> loadDefaultReadConverter() { return loadAllConverter(); } @@ -142,11 +180,11 @@ public class DefaultConverterLoader { * * @return */ - public static Map loadAllConverter() { + public static Map> loadAllConverter() { return allConverter; } - private static void putAllConverter(Converter converter) { + private static void putAllConverter(Converter converter) { allConverter.put(ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()), converter); } diff --git a/src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java b/src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java new file mode 100644 index 00000000..fe24f63d --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java @@ -0,0 +1,10 @@ +package com.alibaba.excel.converters; + +/** + * When implementing convertToExcelData method, pay attention to the reference value may be + * null + * + * @author JiaJu Zhuang + **/ +public interface NullableObjectConverter extends Converter { +} diff --git a/src/main/java/com/alibaba/excel/converters/ReadConverterContext.java b/src/main/java/com/alibaba/excel/converters/ReadConverterContext.java new file mode 100644 index 00000000..e1367065 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/ReadConverterContext.java @@ -0,0 +1,30 @@ +package com.alibaba.excel.converters; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * read converter context + * + * @author Jiaju Zhuang + */ +@Data +@AllArgsConstructor +public class ReadConverterContext { + /** + * Excel cell data.NotNull. + */ + private ReadCellData readCellData; + /** + * Content property.Nullable. + */ + private ExcelContentProperty contentProperty; + /** + * context.NotNull. + */ + private AnalysisContext analysisContext; +} diff --git a/src/main/java/com/alibaba/excel/converters/WriteConverterContext.java b/src/main/java/com/alibaba/excel/converters/WriteConverterContext.java new file mode 100644 index 00000000..36ce56c6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/WriteConverterContext.java @@ -0,0 +1,32 @@ +package com.alibaba.excel.converters; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * write converter context + * + * @author Jiaju Zhuang + */ +@Data +@AllArgsConstructor +public class WriteConverterContext { + + /** + * Java Data.NotNull. + */ + private T value; + + /** + * Content property.Nullable. + */ + private ExcelContentProperty contentProperty; + + /** + * write context + */ + private WriteContext writeContext; +} diff --git a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java index 8dcac0c9..31484562 100644 --- a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java @@ -4,8 +4,9 @@ import java.math.BigDecimal; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -16,7 +17,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class BigDecimalBooleanConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return BigDecimal.class; } @@ -26,7 +27,7 @@ public class BigDecimalBooleanConverter implements Converter { } @Override - public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public BigDecimal convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (cellData.getBooleanValue()) { return BigDecimal.ONE; @@ -35,12 +36,12 @@ public class BigDecimalBooleanConverter implements Converter { } @Override - public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (BigDecimal.ONE.equals(value)) { - return new CellData(Boolean.TRUE); + return new WriteCellData<>(Boolean.TRUE); } - return new CellData(Boolean.FALSE); + return new WriteCellData<>(Boolean.FALSE); } } diff --git a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java index bf9b735f..f1b1285c 100644 --- a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java @@ -4,9 +4,11 @@ import java.math.BigDecimal; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; /** * BigDecimal and number converter @@ -16,7 +18,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class BigDecimalNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return BigDecimal.class; } @@ -26,14 +28,14 @@ public class BigDecimalNumberConverter implements Converter { } @Override - public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public BigDecimal convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getNumberValue(); } @Override - public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(value); + return NumberUtils.formatToCellData(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java index 8c5f0f48..3b117812 100644 --- a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java @@ -5,8 +5,9 @@ import java.text.ParseException; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.NumberUtils; @@ -18,7 +19,7 @@ import com.alibaba.excel.util.NumberUtils; public class BigDecimalStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return BigDecimal.class; } @@ -28,14 +29,14 @@ public class BigDecimalStringConverter implements Converter { } @Override - public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public BigDecimal convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { return NumberUtils.parseBigDecimal(cellData.getStringValue(), contentProperty); } @Override - public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return NumberUtils.formatToCellData(value, contentProperty); + return NumberUtils.formatToCellDataString(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerBooleanConverter.java new file mode 100644 index 00000000..0ac0e6c9 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerBooleanConverter.java @@ -0,0 +1,47 @@ +package com.alibaba.excel.converters.biginteger; + +import java.math.BigInteger; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +/** + * BigInteger and boolean converter + * + * @author Jiaju Zhuang + */ +public class BigIntegerBooleanConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return BigInteger.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.BOOLEAN; + } + + @Override + public BigInteger convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (cellData.getBooleanValue()) { + return BigInteger.ONE; + } + return BigInteger.ZERO; + } + + @Override + public WriteCellData convertToExcelData(BigInteger value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (BigInteger.ONE.equals(value)) { + return new WriteCellData<>(Boolean.TRUE); + } + return new WriteCellData<>(Boolean.FALSE); + } + +} diff --git a/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerNumberConverter.java b/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerNumberConverter.java new file mode 100644 index 00000000..c5957a15 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerNumberConverter.java @@ -0,0 +1,41 @@ +package com.alibaba.excel.converters.biginteger; + +import java.math.BigInteger; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; + +/** + * BigInteger and number converter + * + * @author Jiaju Zhuang + */ +public class BigIntegerNumberConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return BigInteger.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.NUMBER; + } + + @Override + public BigInteger convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + return cellData.getNumberValue().toBigInteger(); + } + + @Override + public WriteCellData convertToExcelData(BigInteger value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + return NumberUtils.formatToCellData(value, contentProperty); + } +} diff --git a/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerStringConverter.java b/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerStringConverter.java new file mode 100644 index 00000000..4894ac16 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/biginteger/BigIntegerStringConverter.java @@ -0,0 +1,42 @@ +package com.alibaba.excel.converters.biginteger; + +import java.math.BigInteger; +import java.text.ParseException; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; + +/** + * BigDecimal and string converter + * + * @author Jiaju Zhuang + */ +public class BigIntegerStringConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return BigInteger.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public BigInteger convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws ParseException { + return NumberUtils.parseBigDecimal(cellData.getStringValue(), contentProperty).toBigInteger(); + } + + @Override + public WriteCellData convertToExcelData(BigInteger value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + return NumberUtils.formatToCellData(value, contentProperty); + } +} diff --git a/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanBooleanConverter.java index 08b83fe9..884f6515 100644 --- a/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.booleanconverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -14,7 +15,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class BooleanBooleanConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Boolean.class; } @@ -24,15 +25,15 @@ public class BooleanBooleanConverter implements Converter { } @Override - public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Boolean convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getBooleanValue(); } @Override - public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(value); + return new WriteCellData<>(value); } } diff --git a/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanNumberConverter.java b/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanNumberConverter.java index a0042eaa..b2438e83 100644 --- a/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanNumberConverter.java @@ -4,8 +4,9 @@ import java.math.BigDecimal; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -15,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; */ public class BooleanNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Boolean.class; } @@ -25,7 +26,7 @@ public class BooleanNumberConverter implements Converter { } @Override - public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Boolean convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (BigDecimal.ONE.compareTo(cellData.getNumberValue()) == 0) { return Boolean.TRUE; @@ -34,12 +35,12 @@ public class BooleanNumberConverter implements Converter { } @Override - public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (value) { - return new CellData(BigDecimal.ONE); + return new WriteCellData<>(BigDecimal.ONE); } - return new CellData(BigDecimal.ZERO); + return new WriteCellData<>(BigDecimal.ZERO); } } diff --git a/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanStringConverter.java b/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanStringConverter.java index e86c6ada..0141ef8d 100644 --- a/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/booleanconverter/BooleanStringConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.booleanconverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -14,7 +15,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class BooleanStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Boolean.class; } @@ -24,15 +25,15 @@ public class BooleanStringConverter implements Converter { } @Override - public Boolean convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Boolean convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return Boolean.valueOf(cellData.getStringValue()); } @Override - public CellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Boolean value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(value.toString()); + return new WriteCellData<>(value.toString()); } } diff --git a/src/main/java/com/alibaba/excel/converters/bytearray/BoxingByteArrayImageConverter.java b/src/main/java/com/alibaba/excel/converters/bytearray/BoxingByteArrayImageConverter.java index c083601b..a1f8d3ac 100644 --- a/src/main/java/com/alibaba/excel/converters/bytearray/BoxingByteArrayImageConverter.java +++ b/src/main/java/com/alibaba/excel/converters/bytearray/BoxingByteArrayImageConverter.java @@ -1,9 +1,8 @@ package com.alibaba.excel.converters.bytearray; import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -13,29 +12,18 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; */ public class BoxingByteArrayImageConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Byte[].class; } @Override - public CellDataTypeEnum supportExcelTypeKey() { - return CellDataTypeEnum.IMAGE; - } - - @Override - public Byte[] convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("Cannot convert images to byte arrays"); - } - - @Override - public CellData convertToExcelData(Byte[] value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Byte[] value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { byte[] byteValue = new byte[value.length]; for (int i = 0; i < value.length; i++) { byteValue[i] = value[i]; } - return new CellData(byteValue); + return new WriteCellData<>(byteValue); } } diff --git a/src/main/java/com/alibaba/excel/converters/bytearray/ByteArrayImageConverter.java b/src/main/java/com/alibaba/excel/converters/bytearray/ByteArrayImageConverter.java index 991999d1..9a871fea 100644 --- a/src/main/java/com/alibaba/excel/converters/bytearray/ByteArrayImageConverter.java +++ b/src/main/java/com/alibaba/excel/converters/bytearray/ByteArrayImageConverter.java @@ -1,9 +1,8 @@ package com.alibaba.excel.converters.bytearray; import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -12,26 +11,16 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; * @author Jiaju Zhuang */ public class ByteArrayImageConverter implements Converter { - @Override - public Class supportJavaTypeKey() { - return byte[].class; - } - - @Override - public CellDataTypeEnum supportExcelTypeKey() { - return CellDataTypeEnum.IMAGE; - } @Override - public byte[] convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("Cannot convert images to byte arrays"); + public Class supportJavaTypeKey() { + return byte[].class; } @Override - public CellData convertToExcelData(byte[] value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(byte[] value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(value); + return new WriteCellData<>(value); } } diff --git a/src/main/java/com/alibaba/excel/converters/byteconverter/ByteBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/byteconverter/ByteBooleanConverter.java index 2b621558..c7da08c4 100644 --- a/src/main/java/com/alibaba/excel/converters/byteconverter/ByteBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/byteconverter/ByteBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.byteconverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -16,7 +17,7 @@ public class ByteBooleanConverter implements Converter { private static final Byte ZERO = (byte)0; @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Byte.class; } @@ -26,7 +27,7 @@ public class ByteBooleanConverter implements Converter { } @Override - public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Byte convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (cellData.getBooleanValue()) { return ONE; @@ -35,12 +36,12 @@ public class ByteBooleanConverter implements Converter { } @Override - public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ONE.equals(value)) { - return new CellData(Boolean.TRUE); + return new WriteCellData<>(Boolean.TRUE); } - return new CellData(Boolean.FALSE); + return new WriteCellData<>(Boolean.FALSE); } } diff --git a/src/main/java/com/alibaba/excel/converters/byteconverter/ByteNumberConverter.java b/src/main/java/com/alibaba/excel/converters/byteconverter/ByteNumberConverter.java index f1facdfb..4103b9cb 100644 --- a/src/main/java/com/alibaba/excel/converters/byteconverter/ByteNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/byteconverter/ByteNumberConverter.java @@ -1,12 +1,12 @@ package com.alibaba.excel.converters.byteconverter; -import java.math.BigDecimal; - import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; /** * Byte and number converter @@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class ByteNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Byte.class; } @@ -26,15 +26,15 @@ public class ByteNumberConverter implements Converter { } @Override - public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Byte convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getNumberValue().byteValue(); } @Override - public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(new BigDecimal(Byte.toString(value))); + return NumberUtils.formatToCellData(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/byteconverter/ByteStringConverter.java b/src/main/java/com/alibaba/excel/converters/byteconverter/ByteStringConverter.java index c96114de..988afbc6 100644 --- a/src/main/java/com/alibaba/excel/converters/byteconverter/ByteStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/byteconverter/ByteStringConverter.java @@ -4,8 +4,9 @@ import java.text.ParseException; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.NumberUtils; @@ -17,7 +18,7 @@ import com.alibaba.excel.util.NumberUtils; public class ByteStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Byte.class; } @@ -27,15 +28,15 @@ public class ByteStringConverter implements Converter { } @Override - public Byte convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Byte convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { return NumberUtils.parseByte(cellData.getStringValue(), contentProperty); } @Override - public CellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Byte value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return NumberUtils.formatToCellData(value, contentProperty); + return NumberUtils.formatToCellDataString(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/date/DateDateConverter.java b/src/main/java/com/alibaba/excel/converters/date/DateDateConverter.java new file mode 100644 index 00000000..29970070 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/date/DateDateConverter.java @@ -0,0 +1,34 @@ +package com.alibaba.excel.converters.date; + +import java.util.Date; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.DateUtils; +import com.alibaba.excel.util.WorkBookUtil; + +/** + * Date and date converter + * + * @author Jiaju Zhuang + */ +public class DateDateConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return Date.class; + } + + @Override + public WriteCellData convertToExcelData(Date value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + WriteCellData cellData = new WriteCellData<>(value); + String format = null; + if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) { + format = contentProperty.getDateTimeFormatProperty().getFormat(); + } + WorkBookUtil.fillDataFormat(cellData, format, DateUtils.defaultDateFormat); + return cellData; + } +} diff --git a/src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java b/src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java index fcc76bb3..34bb7536 100644 --- a/src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java @@ -3,14 +3,15 @@ package com.alibaba.excel.converters.date; import java.math.BigDecimal; import java.util.Date; -import org.apache.poi.ss.usermodel.DateUtil; - import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import org.apache.poi.ss.usermodel.DateUtil; + /** * Date and number converter * @@ -19,7 +20,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class DateNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Date.class; } @@ -29,7 +30,7 @@ public class DateNumberConverter implements Converter { } @Override - public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Date convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { return DateUtil.getJavaDate(cellData.getNumberValue().doubleValue(), @@ -41,13 +42,13 @@ public class DateNumberConverter implements Converter { } @Override - public CellData convertToExcelData(Date value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { - return new CellData( + return new WriteCellData<>( BigDecimal.valueOf(DateUtil.getExcelDate(value, globalConfiguration.getUse1904windowing()))); } else { - return new CellData(BigDecimal.valueOf( + return new WriteCellData<>(BigDecimal.valueOf( DateUtil.getExcelDate(value, contentProperty.getDateTimeFormatProperty().getUse1904windowing()))); } } diff --git a/src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java b/src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java index ed7eb0a4..9941c70e 100644 --- a/src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java @@ -5,8 +5,9 @@ import java.util.Date; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.DateUtils; @@ -17,7 +18,7 @@ import com.alibaba.excel.util.DateUtils; */ public class DateStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Date.class; } @@ -27,7 +28,7 @@ public class DateStringConverter implements Converter { } @Override - public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Date convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { return DateUtils.parseDate(cellData.getStringValue(), null); @@ -38,12 +39,12 @@ public class DateStringConverter implements Converter { } @Override - public CellData convertToExcelData(Date value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { - return new CellData(DateUtils.format(value, null)); + return new WriteCellData<>(DateUtils.format(value, null)); } else { - return new CellData(DateUtils.format(value, contentProperty.getDateTimeFormatProperty().getFormat())); + return new WriteCellData<>(DateUtils.format(value, contentProperty.getDateTimeFormatProperty().getFormat())); } } } diff --git a/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleBooleanConverter.java index cbf0b0b0..3da808e1 100644 --- a/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.doubleconverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -16,7 +17,7 @@ public class DoubleBooleanConverter implements Converter { private static final Double ZERO = 0.0; @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Double.class; } @@ -26,7 +27,7 @@ public class DoubleBooleanConverter implements Converter { } @Override - public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Double convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (cellData.getBooleanValue()) { return ONE; @@ -35,12 +36,12 @@ public class DoubleBooleanConverter implements Converter { } @Override - public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Double value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ONE.equals(value)) { - return new CellData(Boolean.TRUE); + return new WriteCellData<>(Boolean.TRUE); } - return new CellData(Boolean.FALSE); + return new WriteCellData<>(Boolean.FALSE); } } diff --git a/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleNumberConverter.java b/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleNumberConverter.java index 15fbdae3..70bdffb6 100644 --- a/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleNumberConverter.java @@ -1,12 +1,12 @@ package com.alibaba.excel.converters.doubleconverter; -import java.math.BigDecimal; - import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; /** * Double and number converter @@ -16,7 +16,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class DoubleNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Double.class; } @@ -26,15 +26,14 @@ public class DoubleNumberConverter implements Converter { } @Override - public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Double convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getNumberValue().doubleValue(); } @Override - public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Double value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(BigDecimal.valueOf(value)); + return NumberUtils.formatToCellData(value, contentProperty); } - } diff --git a/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleStringConverter.java b/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleStringConverter.java index 2572b4ee..e1951130 100644 --- a/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/doubleconverter/DoubleStringConverter.java @@ -4,8 +4,9 @@ import java.text.ParseException; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.NumberUtils; @@ -17,7 +18,7 @@ import com.alibaba.excel.util.NumberUtils; public class DoubleStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Double.class; } @@ -27,14 +28,14 @@ public class DoubleStringConverter implements Converter { } @Override - public Double convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Double convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { return NumberUtils.parseDouble(cellData.getStringValue(), contentProperty); } @Override - public CellData convertToExcelData(Double value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Double value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return NumberUtils.formatToCellData(value, contentProperty); + return NumberUtils.formatToCellDataString(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/file/FileImageConverter.java b/src/main/java/com/alibaba/excel/converters/file/FileImageConverter.java index 10522154..c8fd6e8b 100644 --- a/src/main/java/com/alibaba/excel/converters/file/FileImageConverter.java +++ b/src/main/java/com/alibaba/excel/converters/file/FileImageConverter.java @@ -4,9 +4,8 @@ import java.io.File; import java.io.IOException; import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.FileUtils; @@ -17,25 +16,13 @@ import com.alibaba.excel.util.FileUtils; */ public class FileImageConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return File.class; } @Override - public CellDataTypeEnum supportExcelTypeKey() { - return CellDataTypeEnum.IMAGE; - } - - @Override - public File convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("Cannot convert images to file"); - } - - @Override - public CellData convertToExcelData(File value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(File value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws IOException { - return new CellData(FileUtils.readFileToByteArray(value)); + return new WriteCellData<>(FileUtils.readFileToByteArray(value)); } - } diff --git a/src/main/java/com/alibaba/excel/converters/floatconverter/FloatBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/floatconverter/FloatBooleanConverter.java index 8fa2a647..1ec6168c 100644 --- a/src/main/java/com/alibaba/excel/converters/floatconverter/FloatBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/floatconverter/FloatBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.floatconverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -16,7 +17,7 @@ public class FloatBooleanConverter implements Converter { private static final Float ZERO = (float)0.0; @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Float.class; } @@ -26,7 +27,7 @@ public class FloatBooleanConverter implements Converter { } @Override - public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Float convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (cellData.getBooleanValue()) { return ONE; @@ -35,12 +36,12 @@ public class FloatBooleanConverter implements Converter { } @Override - public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Float value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ONE.equals(value)) { - return new CellData(Boolean.TRUE); + return new WriteCellData<>(Boolean.TRUE); } - return new CellData(Boolean.FALSE); + return new WriteCellData<>(Boolean.FALSE); } } diff --git a/src/main/java/com/alibaba/excel/converters/floatconverter/FloatNumberConverter.java b/src/main/java/com/alibaba/excel/converters/floatconverter/FloatNumberConverter.java index 69cc22e7..478086e3 100644 --- a/src/main/java/com/alibaba/excel/converters/floatconverter/FloatNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/floatconverter/FloatNumberConverter.java @@ -1,12 +1,13 @@ package com.alibaba.excel.converters.floatconverter; -import java.math.BigDecimal; - import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.converters.WriteConverterContext; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; /** * Float and number converter @@ -16,7 +17,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class FloatNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Float.class; } @@ -26,15 +27,13 @@ public class FloatNumberConverter implements Converter { } @Override - public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Float convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getNumberValue().floatValue(); } @Override - public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - return new CellData(new BigDecimal(Float.toString(value))); + public WriteCellData convertToExcelData(WriteConverterContext context) { + return NumberUtils.formatToCellData(context.getValue(), context.getContentProperty()); } - } diff --git a/src/main/java/com/alibaba/excel/converters/floatconverter/FloatStringConverter.java b/src/main/java/com/alibaba/excel/converters/floatconverter/FloatStringConverter.java index ee2ef551..bd5e9762 100644 --- a/src/main/java/com/alibaba/excel/converters/floatconverter/FloatStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/floatconverter/FloatStringConverter.java @@ -4,8 +4,9 @@ import java.text.ParseException; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.NumberUtils; @@ -17,7 +18,7 @@ import com.alibaba.excel.util.NumberUtils; public class FloatStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Float.class; } @@ -27,14 +28,14 @@ public class FloatStringConverter implements Converter { } @Override - public Float convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Float convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { return NumberUtils.parseFloat(cellData.getStringValue(), contentProperty); } @Override - public CellData convertToExcelData(Float value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Float value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return NumberUtils.formatToCellData(value, contentProperty); + return NumberUtils.formatToCellDataString(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/inputstream/InputStreamImageConverter.java b/src/main/java/com/alibaba/excel/converters/inputstream/InputStreamImageConverter.java index abc2fe68..ff8492f0 100644 --- a/src/main/java/com/alibaba/excel/converters/inputstream/InputStreamImageConverter.java +++ b/src/main/java/com/alibaba/excel/converters/inputstream/InputStreamImageConverter.java @@ -4,9 +4,8 @@ import java.io.IOException; import java.io.InputStream; import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.IoUtils; @@ -17,25 +16,14 @@ import com.alibaba.excel.util.IoUtils; */ public class InputStreamImageConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return InputStream.class; } @Override - public CellDataTypeEnum supportExcelTypeKey() { - return CellDataTypeEnum.IMAGE; - } - - @Override - public InputStream convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("Cannot convert images to input stream"); - } - - @Override - public CellData convertToExcelData(InputStream value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(InputStream value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws IOException { - return new CellData(IoUtils.toByteArray(value)); + return new WriteCellData<>(IoUtils.toByteArray(value)); } } diff --git a/src/main/java/com/alibaba/excel/converters/integer/IntegerBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/integer/IntegerBooleanConverter.java index 541de08a..e3f13068 100644 --- a/src/main/java/com/alibaba/excel/converters/integer/IntegerBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/integer/IntegerBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.integer; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -16,7 +17,7 @@ public class IntegerBooleanConverter implements Converter { private static final Integer ZERO = 0; @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Integer.class; } @@ -26,7 +27,7 @@ public class IntegerBooleanConverter implements Converter { } @Override - public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (cellData.getBooleanValue()) { return ONE; @@ -35,12 +36,12 @@ public class IntegerBooleanConverter implements Converter { } @Override - public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ONE.equals(value)) { - return new CellData(Boolean.TRUE); + return new WriteCellData<>(Boolean.TRUE); } - return new CellData(Boolean.FALSE); + return new WriteCellData<>(Boolean.FALSE); } } diff --git a/src/main/java/com/alibaba/excel/converters/integer/IntegerNumberConverter.java b/src/main/java/com/alibaba/excel/converters/integer/IntegerNumberConverter.java index 117d4c11..203aa1ac 100644 --- a/src/main/java/com/alibaba/excel/converters/integer/IntegerNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/integer/IntegerNumberConverter.java @@ -1,12 +1,13 @@ package com.alibaba.excel.converters.integer; -import java.math.BigDecimal; - import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.converters.WriteConverterContext; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; /** * Integer and number converter @@ -16,7 +17,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class IntegerNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Integer.class; } @@ -26,15 +27,14 @@ public class IntegerNumberConverter implements Converter { } @Override - public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getNumberValue().intValue(); } @Override - public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - return new CellData(new BigDecimal(Integer.toString(value))); + public WriteCellData convertToExcelData(WriteConverterContext context) { + return NumberUtils.formatToCellData(context.getValue(), context.getContentProperty()); } } diff --git a/src/main/java/com/alibaba/excel/converters/integer/IntegerStringConverter.java b/src/main/java/com/alibaba/excel/converters/integer/IntegerStringConverter.java index 07bc1b77..62dce6e6 100644 --- a/src/main/java/com/alibaba/excel/converters/integer/IntegerStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/integer/IntegerStringConverter.java @@ -4,8 +4,9 @@ import java.text.ParseException; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.NumberUtils; @@ -17,7 +18,7 @@ import com.alibaba.excel.util.NumberUtils; public class IntegerStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Integer.class; } @@ -27,14 +28,14 @@ public class IntegerStringConverter implements Converter { } @Override - public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Integer convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { return NumberUtils.parseInteger(cellData.getStringValue(), contentProperty); } @Override - public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return NumberUtils.formatToCellData(value, contentProperty); + return NumberUtils.formatToCellDataString(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateNumberConverter.java b/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateNumberConverter.java new file mode 100644 index 00000000..f57f0bdc --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateNumberConverter.java @@ -0,0 +1,55 @@ +package com.alibaba.excel.converters.localdatetime; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import org.apache.poi.ss.usermodel.DateUtil; + +/** + * LocalDateTime and number converter + * + * @author Jiaju Zhuang + */ +public class LocalDateNumberConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return LocalDateTime.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.NUMBER; + } + + @Override + public LocalDateTime convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return DateUtil.getLocalDateTime(cellData.getNumberValue().doubleValue(), + globalConfiguration.getUse1904windowing()); + } else { + return DateUtil.getLocalDateTime(cellData.getNumberValue().doubleValue(), + contentProperty.getDateTimeFormatProperty().getUse1904windowing()); + } + } + + @Override + public WriteCellData convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return new WriteCellData<>( + BigDecimal.valueOf(DateUtil.getExcelDate(value, globalConfiguration.getUse1904windowing()))); + } else { + return new WriteCellData<>(BigDecimal.valueOf( + DateUtil.getExcelDate(value, contentProperty.getDateTimeFormatProperty().getUse1904windowing()))); + } + } +} diff --git a/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeDateConverter.java b/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeDateConverter.java new file mode 100644 index 00000000..072a7864 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeDateConverter.java @@ -0,0 +1,34 @@ +package com.alibaba.excel.converters.localdatetime; + +import java.time.LocalDateTime; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.DateUtils; +import com.alibaba.excel.util.WorkBookUtil; + +/** + * Date and date converter + * + * @author Jiaju Zhuang + */ +public class LocalDateTimeDateConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return LocalDateTime.class; + } + + @Override + public WriteCellData convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + WriteCellData cellData = new WriteCellData<>(value); + String format = null; + if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) { + format = contentProperty.getDateTimeFormatProperty().getFormat(); + } + WorkBookUtil.fillDataFormat(cellData, format, DateUtils.defaultDateFormat); + return cellData; + } +} diff --git a/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeStringConverter.java b/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeStringConverter.java new file mode 100644 index 00000000..56aee318 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/localdatetime/LocalDateTimeStringConverter.java @@ -0,0 +1,52 @@ +package com.alibaba.excel.converters.localdatetime; + +import java.text.ParseException; +import java.time.LocalDateTime; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.DateUtils; + +/** + * LocalDateTime and string converter + * + * @author Jiaju Zhuang + */ +public class LocalDateTimeStringConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return LocalDateTime.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public LocalDateTime convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws ParseException { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return DateUtils.parseLocalDateTime(cellData.getStringValue(), null, globalConfiguration.getLocale()); + } else { + return DateUtils.parseLocalDateTime(cellData.getStringValue(), + contentProperty.getDateTimeFormatProperty().getFormat(), globalConfiguration.getLocale()); + } + } + + @Override + public WriteCellData convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) { + return new WriteCellData<>(DateUtils.format(value, null, globalConfiguration.getLocale())); + } else { + return new WriteCellData<>( + DateUtils.format(value, contentProperty.getDateTimeFormatProperty().getFormat(), + globalConfiguration.getLocale())); + } + } +} diff --git a/src/main/java/com/alibaba/excel/converters/longconverter/LongBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/longconverter/LongBooleanConverter.java index 6ee0217b..d123ed66 100644 --- a/src/main/java/com/alibaba/excel/converters/longconverter/LongBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/longconverter/LongBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.longconverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -16,7 +17,7 @@ public class LongBooleanConverter implements Converter { private static final Long ZERO = 0L; @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Long.class; } @@ -26,7 +27,7 @@ public class LongBooleanConverter implements Converter { } @Override - public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Long convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (cellData.getBooleanValue()) { return ONE; @@ -35,12 +36,12 @@ public class LongBooleanConverter implements Converter { } @Override - public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Long value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ONE.equals(value)) { - return new CellData(Boolean.TRUE); + return new WriteCellData<>(Boolean.TRUE); } - return new CellData(Boolean.FALSE); + return new WriteCellData<>(Boolean.FALSE); } } diff --git a/src/main/java/com/alibaba/excel/converters/longconverter/LongNumberConverter.java b/src/main/java/com/alibaba/excel/converters/longconverter/LongNumberConverter.java index 8058d624..aee15b5b 100644 --- a/src/main/java/com/alibaba/excel/converters/longconverter/LongNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/longconverter/LongNumberConverter.java @@ -1,12 +1,13 @@ package com.alibaba.excel.converters.longconverter; -import java.math.BigDecimal; - import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.converters.WriteConverterContext; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; /** * Long and number converter @@ -16,7 +17,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class LongNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Long.class; } @@ -26,15 +27,14 @@ public class LongNumberConverter implements Converter { } @Override - public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Long convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getNumberValue().longValue(); } @Override - public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - return new CellData(BigDecimal.valueOf(value)); + public WriteCellData convertToExcelData(WriteConverterContext context) { + return NumberUtils.formatToCellData(context.getValue(), context.getContentProperty()); } } diff --git a/src/main/java/com/alibaba/excel/converters/longconverter/LongStringConverter.java b/src/main/java/com/alibaba/excel/converters/longconverter/LongStringConverter.java index 06e94f03..26ffcc81 100644 --- a/src/main/java/com/alibaba/excel/converters/longconverter/LongStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/longconverter/LongStringConverter.java @@ -4,8 +4,9 @@ import java.text.ParseException; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.NumberUtils; @@ -17,7 +18,7 @@ import com.alibaba.excel.util.NumberUtils; public class LongStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Long.class; } @@ -27,14 +28,14 @@ public class LongStringConverter implements Converter { } @Override - public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Long convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { return NumberUtils.parseLong(cellData.getStringValue(), contentProperty); } @Override - public CellData convertToExcelData(Long value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Long value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return NumberUtils.formatToCellData(value, contentProperty); + return NumberUtils.formatToCellDataString(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/shortconverter/ShortBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/shortconverter/ShortBooleanConverter.java index 2c0cc61d..1f0517ee 100644 --- a/src/main/java/com/alibaba/excel/converters/shortconverter/ShortBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/shortconverter/ShortBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.shortconverter; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -16,7 +17,7 @@ public class ShortBooleanConverter implements Converter { private static final Short ZERO = 0; @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Short.class; } @@ -26,7 +27,7 @@ public class ShortBooleanConverter implements Converter { } @Override - public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Short convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (cellData.getBooleanValue()) { return ONE; @@ -35,12 +36,12 @@ public class ShortBooleanConverter implements Converter { } @Override - public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Short value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ONE.equals(value)) { - return new CellData(Boolean.TRUE); + return new WriteCellData<>(Boolean.TRUE); } - return new CellData(Boolean.FALSE); + return new WriteCellData<>(Boolean.FALSE); } } diff --git a/src/main/java/com/alibaba/excel/converters/shortconverter/ShortNumberConverter.java b/src/main/java/com/alibaba/excel/converters/shortconverter/ShortNumberConverter.java index 357c6aeb..d0568606 100644 --- a/src/main/java/com/alibaba/excel/converters/shortconverter/ShortNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/shortconverter/ShortNumberConverter.java @@ -1,12 +1,13 @@ package com.alibaba.excel.converters.shortconverter; -import java.math.BigDecimal; - import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.converters.WriteConverterContext; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.NumberUtils; /** * Short and number converter @@ -16,7 +17,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class ShortNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Short.class; } @@ -26,15 +27,13 @@ public class ShortNumberConverter implements Converter { } @Override - public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Short convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getNumberValue().shortValue(); } @Override - public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - return new CellData(new BigDecimal(Short.toString(value))); + public WriteCellData convertToExcelData(WriteConverterContext context) { + return NumberUtils.formatToCellData(context.getValue(), context.getContentProperty()); } - } diff --git a/src/main/java/com/alibaba/excel/converters/shortconverter/ShortStringConverter.java b/src/main/java/com/alibaba/excel/converters/shortconverter/ShortStringConverter.java index a683a038..497fdee9 100644 --- a/src/main/java/com/alibaba/excel/converters/shortconverter/ShortStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/shortconverter/ShortStringConverter.java @@ -4,8 +4,9 @@ import java.text.ParseException; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.NumberUtils; @@ -17,7 +18,7 @@ import com.alibaba.excel.util.NumberUtils; public class ShortStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return Short.class; } @@ -27,14 +28,14 @@ public class ShortStringConverter implements Converter { } @Override - public Short convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public Short convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws ParseException { return NumberUtils.parseShort(cellData.getStringValue(), contentProperty); } @Override - public CellData convertToExcelData(Short value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(Short value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return NumberUtils.formatToCellData(value, contentProperty); + return NumberUtils.formatToCellDataString(value, contentProperty); } } diff --git a/src/main/java/com/alibaba/excel/converters/string/StringBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/string/StringBooleanConverter.java index c405de5e..704a18b4 100644 --- a/src/main/java/com/alibaba/excel/converters/string/StringBooleanConverter.java +++ b/src/main/java/com/alibaba/excel/converters/string/StringBooleanConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.string; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -14,7 +15,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; public class StringBooleanConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String.class; } @@ -24,15 +25,15 @@ public class StringBooleanConverter implements Converter { } @Override - public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public String convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getBooleanValue().toString(); } @Override - public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(Boolean.valueOf(value)); + return new WriteCellData<>(Boolean.valueOf(value)); } } diff --git a/src/main/java/com/alibaba/excel/converters/string/StringErrorConverter.java b/src/main/java/com/alibaba/excel/converters/string/StringErrorConverter.java index 66112e1a..1456d80f 100644 --- a/src/main/java/com/alibaba/excel/converters/string/StringErrorConverter.java +++ b/src/main/java/com/alibaba/excel/converters/string/StringErrorConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.string; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -13,7 +14,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; */ public class StringErrorConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String.class; } @@ -23,15 +24,15 @@ public class StringErrorConverter implements Converter { } @Override - public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public String convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getStringValue(); } @Override - public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(CellDataTypeEnum.ERROR, value); + return new WriteCellData<>(CellDataTypeEnum.ERROR, value); } } diff --git a/src/main/java/com/alibaba/excel/converters/string/StringImageConverter.java b/src/main/java/com/alibaba/excel/converters/string/StringImageConverter.java index 931d4fa9..fb262e19 100644 --- a/src/main/java/com/alibaba/excel/converters/string/StringImageConverter.java +++ b/src/main/java/com/alibaba/excel/converters/string/StringImageConverter.java @@ -4,9 +4,8 @@ import java.io.File; import java.io.IOException; import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.FileUtils; @@ -17,25 +16,14 @@ import com.alibaba.excel.util.FileUtils; */ public class StringImageConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String.class; } @Override - public CellDataTypeEnum supportExcelTypeKey() { - return CellDataTypeEnum.IMAGE; - } - - @Override - public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("Cannot convert images to string"); - } - - @Override - public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws IOException { - return new CellData(FileUtils.readFileToByteArray(new File(value))); + return new WriteCellData<>(FileUtils.readFileToByteArray(new File(value))); } } diff --git a/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java b/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java index 693c1120..0d0813d0 100644 --- a/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java +++ b/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java @@ -2,18 +2,19 @@ package com.alibaba.excel.converters.string; import java.math.BigDecimal; -import org.apache.poi.ss.usermodel.DateUtil; - import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.NumberDataFormatterUtils; import com.alibaba.excel.util.NumberUtils; import com.alibaba.excel.util.StringUtils; +import org.apache.poi.ss.usermodel.DateUtil; + /** * String and number converter * @@ -22,7 +23,7 @@ import com.alibaba.excel.util.StringUtils; public class StringNumberConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String.class; } @@ -32,7 +33,7 @@ public class StringNumberConverter implements Converter { } @Override - public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public String convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { // If there are "DateTimeFormat", read as date if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) { @@ -46,17 +47,20 @@ public class StringNumberConverter implements Converter { return NumberUtils.format(cellData.getNumberValue(), contentProperty); } // Excel defines formatting - if (cellData.getDataFormat() != null && !StringUtils.isEmpty(cellData.getDataFormatString())) { - return NumberDataFormatterUtils.format(cellData.getNumberValue(), cellData.getDataFormat(), - cellData.getDataFormatString(), globalConfiguration); + boolean hasDataFormatData = cellData.getDataFormatData() != null + && cellData.getDataFormatData().getIndex() != null && !StringUtils.isEmpty( + cellData.getDataFormatData().getFormat()); + if (hasDataFormatData) { + return NumberDataFormatterUtils.format(cellData.getNumberValue(), + cellData.getDataFormatData().getIndex(), cellData.getDataFormatData().getFormat(), globalConfiguration); } // Default conversion number return NumberUtils.format(cellData.getNumberValue(), contentProperty); } @Override - public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(new BigDecimal(value)); + return new WriteCellData<>(new BigDecimal(value)); } } diff --git a/src/main/java/com/alibaba/excel/converters/string/StringStringConverter.java b/src/main/java/com/alibaba/excel/converters/string/StringStringConverter.java index df1b1e14..5edc6b16 100644 --- a/src/main/java/com/alibaba/excel/converters/string/StringStringConverter.java +++ b/src/main/java/com/alibaba/excel/converters/string/StringStringConverter.java @@ -2,8 +2,9 @@ package com.alibaba.excel.converters.string; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -13,7 +14,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; */ public class StringStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String.class; } @@ -23,15 +24,15 @@ public class StringStringConverter implements Converter { } @Override - public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public String convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getStringValue(); } @Override - public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(value); + return new WriteCellData<>(value); } } diff --git a/src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java b/src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java index b622d66d..7daa7cab 100644 --- a/src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java +++ b/src/main/java/com/alibaba/excel/converters/url/UrlImageConverter.java @@ -3,45 +3,40 @@ package com.alibaba.excel.converters.url; import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.net.URLConnection; import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.IoUtils; /** * Url and image converter * - * @since 2.1.1 * @author Jiaju Zhuang + * @since 2.1.1 */ public class UrlImageConverter implements Converter { - @Override - public Class supportJavaTypeKey() { - return URL.class; - } + public static int urlConnectTimeout = 1000; + public static int urlReadTimeout = 5000; @Override - public CellDataTypeEnum supportExcelTypeKey() { - return CellDataTypeEnum.IMAGE; - } - - @Override - public URL convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, - GlobalConfiguration globalConfiguration) { - throw new UnsupportedOperationException("Cannot convert images to url."); + public Class supportJavaTypeKey() { + return URL.class; } @Override - public CellData convertToExcelData(URL value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(URL value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws IOException { InputStream inputStream = null; try { - inputStream = value.openStream(); + URLConnection urlConnection = value.openConnection(); + urlConnection.setConnectTimeout(urlConnectTimeout); + urlConnection.setReadTimeout(urlReadTimeout); + inputStream = urlConnection.getInputStream(); byte[] bytes = IoUtils.toByteArray(inputStream); - return new CellData(bytes); + return new WriteCellData<>(bytes); } finally { if (inputStream != null) { inputStream.close(); diff --git a/src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java b/src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java index b48e40b2..0f1a46cf 100644 --- a/src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java +++ b/src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java @@ -37,11 +37,17 @@ public enum CellDataTypeEnum { */ ERROR, /** - * Images are currently supported only when writing + * date. Support only when writing. */ - IMAGE; + DATE, + /** + * rich text string.Support only when writing. + */ + RICH_TEXT_STRING, + ; private static final Map TYPE_ROUTING_MAP = new HashMap(16); + static { TYPE_ROUTING_MAP.put("s", STRING); TYPE_ROUTING_MAP.put("str", DIRECT_STRING); diff --git a/src/main/java/com/alibaba/excel/enums/NumericCellTypeEnum.java b/src/main/java/com/alibaba/excel/enums/NumericCellTypeEnum.java new file mode 100644 index 00000000..22001f13 --- /dev/null +++ b/src/main/java/com/alibaba/excel/enums/NumericCellTypeEnum.java @@ -0,0 +1,22 @@ +package com.alibaba.excel.enums; + +import org.apache.poi.ss.usermodel.CellType; + +/** + * Used to supplement {@link CellType}. + * + * Cannot distinguish between date and number in write case. + * + * @author Jiaju Zhuang + */ +public enum NumericCellTypeEnum { + /** + * number + */ + NUMBER, + /** + * date. Support only when writing. + */ + DATE, + ; +} diff --git a/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java b/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java index 1e93397e..365336b7 100644 --- a/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java +++ b/src/main/java/com/alibaba/excel/event/AbstractIgnoreExceptionReadListener.java @@ -8,7 +8,9 @@ import com.alibaba.excel.read.listener.ReadListener; * Receives the return of each piece of data parsed * * @author jipengfei + * @deprecated Use directly {@link ReadListener} */ +@Deprecated public abstract class AbstractIgnoreExceptionReadListener implements ReadListener { /** @@ -24,10 +26,8 @@ public abstract class AbstractIgnoreExceptionReadListener implements ReadList /** * The current method is called when extra information is returned * - * @param extra - * extra information - * @param context - * analysis context + * @param extra extra information + * @param context analysis context */ @Override public void extra(CellExtra extra, AnalysisContext context) {} diff --git a/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java b/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java index 4b1b802a..bc94d75e 100644 --- a/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java +++ b/src/main/java/com/alibaba/excel/event/AnalysisEventListener.java @@ -3,8 +3,8 @@ package com.alibaba.excel.event; import java.util.Map; import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellExtra; +import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.util.ConverterUtils; @@ -16,7 +16,7 @@ import com.alibaba.excel.util.ConverterUtils; public abstract class AnalysisEventListener implements ReadListener { @Override - public void invokeHead(Map headMap, AnalysisContext context) { + public void invokeHead(Map> headMap, AnalysisContext context) { invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context), context); } diff --git a/src/main/java/com/alibaba/excel/event/Handler.java b/src/main/java/com/alibaba/excel/event/Handler.java index 2fe304f0..4b32be0c 100644 --- a/src/main/java/com/alibaba/excel/event/Handler.java +++ b/src/main/java/com/alibaba/excel/event/Handler.java @@ -1,8 +1,21 @@ package com.alibaba.excel.event; +import com.alibaba.excel.constant.OrderConstant; + /** * Intercepts handle some business logic * * @author Jiaju Zhuang **/ -public interface Handler {} +public interface Handler extends Order { + + /** + * handler order + * + * @return order + */ + @Override + default int order() { + return OrderConstant.DEFAULT_ORDER; + } +} diff --git a/src/main/java/com/alibaba/excel/event/WriteHandler.java b/src/main/java/com/alibaba/excel/event/WriteHandler.java deleted file mode 100644 index 8c981ffc..00000000 --- a/src/main/java/com/alibaba/excel/event/WriteHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.alibaba.excel.event; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; - -/** - * - * @author jipengfei - * @deprecated please use {@link com.alibaba.excel.write.handler.WriteHandler} - */ -@Deprecated -public interface WriteHandler { - - /** - * Custom operation after creating each sheet - * - * @param sheetNo - * @param sheet - */ - void sheet(int sheetNo, Sheet sheet); - - /** - * Custom operation after creating each row - * - * @param rowNum - * @param row - */ - void row(int rowNum, Row row); - - /** - * Custom operation after creating each cell - * - * @param cellNum - * @param cell - */ - void cell(int cellNum, Cell cell); -} diff --git a/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java b/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java index 5198c20f..1cb9c934 100644 --- a/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java +++ b/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java @@ -1,14 +1,17 @@ package com.alibaba.excel.exception; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.CellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import lombok.Data; + /** * Data convert exception * * @author Jiaju Zhuang */ +@Data public class ExcelDataConvertException extends RuntimeException { /** * NotNull. @@ -21,7 +24,7 @@ public class ExcelDataConvertException extends RuntimeException { /** * NotNull. */ - private CellData cellData; + private CellData cellData; /** * Nullable.Only when the header is configured and when the class header is used is not null. * @@ -47,35 +50,4 @@ public class ExcelDataConvertException extends RuntimeException { this.excelContentProperty = excelContentProperty; } - public Integer getRowIndex() { - return rowIndex; - } - - public void setRowIndex(Integer rowIndex) { - this.rowIndex = rowIndex; - } - - public Integer getColumnIndex() { - return columnIndex; - } - - public void setColumnIndex(Integer columnIndex) { - this.columnIndex = columnIndex; - } - - public ExcelContentProperty getExcelContentProperty() { - return excelContentProperty; - } - - public void setExcelContentProperty(ExcelContentProperty excelContentProperty) { - this.excelContentProperty = excelContentProperty; - } - - public CellData getCellData() { - return cellData; - } - - public void setCellData(CellData cellData) { - this.cellData = cellData; - } } diff --git a/src/main/java/com/alibaba/excel/metadata/AbstractCell.java b/src/main/java/com/alibaba/excel/metadata/AbstractCell.java index 5cea37cf..6647cf0c 100644 --- a/src/main/java/com/alibaba/excel/metadata/AbstractCell.java +++ b/src/main/java/com/alibaba/excel/metadata/AbstractCell.java @@ -1,10 +1,13 @@ package com.alibaba.excel.metadata; +import lombok.Data; + /** * cell * * @author Jiaju Zhuang **/ +@Data public class AbstractCell implements Cell { /** * Row index @@ -14,20 +17,4 @@ public class AbstractCell implements Cell { * Column index */ private Integer columnIndex; - - public Integer getRowIndex() { - return rowIndex; - } - - public void setRowIndex(Integer rowIndex) { - this.rowIndex = rowIndex; - } - - public Integer getColumnIndex() { - return columnIndex; - } - - public void setColumnIndex(Integer columnIndex) { - this.columnIndex = columnIndex; - } } diff --git a/src/main/java/com/alibaba/excel/metadata/AbstractHolder.java b/src/main/java/com/alibaba/excel/metadata/AbstractHolder.java index f7cb1ced..735a0623 100644 --- a/src/main/java/com/alibaba/excel/metadata/AbstractHolder.java +++ b/src/main/java/com/alibaba/excel/metadata/AbstractHolder.java @@ -1,16 +1,20 @@ package com.alibaba.excel.metadata; import java.util.List; -import java.util.Locale; import java.util.Map; import com.alibaba.excel.converters.Converter; +import lombok.Data; +import lombok.NoArgsConstructor; + /** * Write/read holder * * @author Jiaju Zhuang */ +@Data +@NoArgsConstructor public abstract class AbstractHolder implements ConfigurationHolder { /** * Record whether it's new or from cache @@ -23,7 +27,7 @@ public abstract class AbstractHolder implements ConfigurationHolder { /** * You can only choose one of the {@link AbstractHolder#head} and {@link AbstractHolder#clazz} */ - private Class clazz; + private Class clazz; /** * Some global variables */ @@ -34,7 +38,7 @@ public abstract class AbstractHolder implements ConfigurationHolder { *

* Write key: */ - private Map converterMap; + private Map> converterMap; public AbstractHolder(BasicParameter basicParameter, AbstractHolder prentAbstractHolder) { this.newInitialization = Boolean.TRUE; @@ -50,19 +54,24 @@ public abstract class AbstractHolder implements ConfigurationHolder { } this.globalConfiguration = new GlobalConfiguration(); if (basicParameter.getAutoTrim() == null) { - if (prentAbstractHolder == null) { - globalConfiguration.setAutoTrim(Boolean.TRUE); - } else { + if (prentAbstractHolder != null) { globalConfiguration.setAutoTrim(prentAbstractHolder.getGlobalConfiguration().getAutoTrim()); } } else { globalConfiguration.setAutoTrim(basicParameter.getAutoTrim()); } + if (basicParameter.getUse1904windowing() == null) { + if (prentAbstractHolder != null) { + globalConfiguration.setUse1904windowing( + prentAbstractHolder.getGlobalConfiguration().getUse1904windowing()); + } + } else { + globalConfiguration.setUse1904windowing(basicParameter.getUse1904windowing()); + } + if (basicParameter.getLocale() == null) { - if (prentAbstractHolder == null) { - globalConfiguration.setLocale(Locale.getDefault()); - } else { + if (prentAbstractHolder != null) { globalConfiguration.setLocale(prentAbstractHolder.getGlobalConfiguration().getLocale()); } } else { @@ -71,48 +80,8 @@ public abstract class AbstractHolder implements ConfigurationHolder { } - public Boolean getNewInitialization() { - return newInitialization; - } - - public void setNewInitialization(Boolean newInitialization) { - this.newInitialization = newInitialization; - } - - public List> getHead() { - return head; - } - - public void setHead(List> head) { - this.head = head; - } - - public Class getClazz() { - return clazz; - } - - public void setClazz(Class clazz) { - this.clazz = clazz; - } - - public GlobalConfiguration getGlobalConfiguration() { - return globalConfiguration; - } - - public void setGlobalConfiguration(GlobalConfiguration globalConfiguration) { - this.globalConfiguration = globalConfiguration; - } - - public Map getConverterMap() { - return converterMap; - } - - public void setConverterMap(Map converterMap) { - this.converterMap = converterMap; - } - @Override - public Map converterMap() { + public Map> converterMap() { return getConverterMap(); } diff --git a/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java b/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java index 66df25b6..319c5ab6 100644 --- a/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java +++ b/src/main/java/com/alibaba/excel/metadata/AbstractParameterBuilder.java @@ -1,10 +1,10 @@ package com.alibaba.excel.metadata; -import java.util.ArrayList; import java.util.List; import java.util.Locale; import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.util.ListUtils; /** * ExcelBuilder @@ -29,7 +29,7 @@ public abstract class AbstractParameterBuilder clazz) { parameter().setClazz(clazz); return self(); } @@ -40,9 +40,9 @@ public abstract class AbstractParameterBuilder converter) { if (parameter().getCustomConverterList() == null) { - parameter().setCustomConverterList(new ArrayList()); + parameter().setCustomConverterList(ListUtils.newArrayList()); } parameter().getCustomConverterList().add(converter); return self(); diff --git a/src/main/java/com/alibaba/excel/metadata/BaseRowModel.java b/src/main/java/com/alibaba/excel/metadata/BaseRowModel.java deleted file mode 100644 index 7df131e4..00000000 --- a/src/main/java/com/alibaba/excel/metadata/BaseRowModel.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.alibaba.excel.metadata; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.poi.ss.usermodel.CellStyle; - -import com.alibaba.excel.annotation.ExcelIgnore; - -/** - * Excel基础模型 - * - * @author jipengfei - * @deprecated Now you don't need to extend any classes - */ -@Deprecated -public class BaseRowModel { - - /** - * 每列样式 - */ - @ExcelIgnore - private Map cellStyleMap = new HashMap(); - - public void addStyle(Integer row, CellStyle cellStyle) { - cellStyleMap.put(row, cellStyle); - } - - public CellStyle getStyle(Integer row) { - return cellStyleMap.get(row); - } - - public Map getCellStyleMap() { - return cellStyleMap; - } - - public void setCellStyleMap(Map cellStyleMap) { - this.cellStyleMap = cellStyleMap; - } -} diff --git a/src/main/java/com/alibaba/excel/metadata/BasicParameter.java b/src/main/java/com/alibaba/excel/metadata/BasicParameter.java index 5baf5cf5..f574f10e 100644 --- a/src/main/java/com/alibaba/excel/metadata/BasicParameter.java +++ b/src/main/java/com/alibaba/excel/metadata/BasicParameter.java @@ -5,11 +5,14 @@ import java.util.Locale; import com.alibaba.excel.converters.Converter; +import lombok.Data; + /** * Basic parameter * * @author Jiaju Zhuang **/ +@Data public class BasicParameter { /** * You can only choose one of the {@link BasicParameter#head} and {@link BasicParameter#clazz} @@ -18,11 +21,11 @@ public class BasicParameter { /** * You can only choose one of the {@link BasicParameter#head} and {@link BasicParameter#clazz} */ - private Class clazz; + private Class clazz; /** * Custom type conversions override the default */ - private List customConverterList; + private List> customConverterList; /** * Automatic trim includes sheet name and content */ @@ -47,60 +50,4 @@ public class BasicParameter { * default is false */ private Boolean useScientificFormat; - - public List> getHead() { - return head; - } - - public void setHead(List> head) { - this.head = head; - } - - public Class getClazz() { - return clazz; - } - - public void setClazz(Class clazz) { - this.clazz = clazz; - } - - public List getCustomConverterList() { - return customConverterList; - } - - public void setCustomConverterList(List customConverterList) { - this.customConverterList = customConverterList; - } - - public Boolean getAutoTrim() { - return autoTrim; - } - - public void setAutoTrim(Boolean autoTrim) { - this.autoTrim = autoTrim; - } - - public Boolean getUse1904windowing() { - return use1904windowing; - } - - public void setUse1904windowing(Boolean use1904windowing) { - this.use1904windowing = use1904windowing; - } - - public Locale getLocale() { - return locale; - } - - public void setLocale(Locale locale) { - this.locale = locale; - } - - public Boolean getUseScientificFormat() { - return useScientificFormat; - } - - public void setUseScientificFormat(Boolean useScientificFormat) { - this.useScientificFormat = useScientificFormat; - } } diff --git a/src/main/java/com/alibaba/excel/metadata/CellData.java b/src/main/java/com/alibaba/excel/metadata/CellData.java deleted file mode 100644 index 2124e103..00000000 --- a/src/main/java/com/alibaba/excel/metadata/CellData.java +++ /dev/null @@ -1,286 +0,0 @@ -package com.alibaba.excel.metadata; - -import java.math.BigDecimal; - -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.util.StringUtils; - -/** - * Excel internal cell data. - * - *

- * - * @author Jiaju Zhuang - */ -public class CellData extends AbstractCell { - private CellDataTypeEnum type; - /** - * {@link CellDataTypeEnum#NUMBER} - */ - private BigDecimal numberValue; - /** - * {@link CellDataTypeEnum#STRING} and{@link CellDataTypeEnum#ERROR} - */ - private String stringValue; - /** - * {@link CellDataTypeEnum#BOOLEAN} - */ - private Boolean booleanValue; - private Boolean formula; - private String formulaValue; - private byte[] imageValue; - /** - * The number formatting.Currently only supported when reading - */ - private Integer dataFormat; - /** - * The string of number formatting.Currently only supported when reading - */ - private String dataFormatString; - /** - * The resulting converted data. - */ - private T data; - - public CellData(CellData other) { - this.type = other.type; - this.numberValue = other.numberValue; - this.stringValue = other.stringValue; - this.booleanValue = other.booleanValue; - this.formula = other.formula; - this.formulaValue = other.formulaValue; - this.imageValue = other.imageValue; - this.dataFormat = other.dataFormat; - this.dataFormatString = other.dataFormatString; - this.data = other.data; - } - - public CellData() {} - - public CellData(T data) { - this.data = data; - } - - public CellData(T data, String formulaValue) { - this.data = data; - this.formula = Boolean.TRUE; - this.formulaValue = formulaValue; - } - - public CellData(String stringValue) { - this(CellDataTypeEnum.STRING, stringValue); - } - - public CellData(CellDataTypeEnum type, String stringValue) { - if (type != CellDataTypeEnum.STRING && type != CellDataTypeEnum.ERROR) { - throw new IllegalArgumentException("Only support CellDataTypeEnum.STRING and CellDataTypeEnum.ERROR"); - } - if (stringValue == null) { - throw new IllegalArgumentException("StringValue can not be null"); - } - this.type = type; - this.stringValue = stringValue; - this.formula = Boolean.FALSE; - } - - public CellData(BigDecimal numberValue) { - if (numberValue == null) { - throw new IllegalArgumentException("DoubleValue can not be null"); - } - this.type = CellDataTypeEnum.NUMBER; - this.numberValue = numberValue; - this.formula = Boolean.FALSE; - } - - public CellData(byte[] imageValue) { - if (imageValue == null) { - throw new IllegalArgumentException("ImageValue can not be null"); - } - this.type = CellDataTypeEnum.IMAGE; - this.imageValue = imageValue; - this.formula = Boolean.FALSE; - } - - public CellData(Boolean booleanValue) { - if (booleanValue == null) { - throw new IllegalArgumentException("BooleanValue can not be null"); - } - this.type = CellDataTypeEnum.BOOLEAN; - this.booleanValue = booleanValue; - this.formula = Boolean.FALSE; - } - - public CellData(CellDataTypeEnum type) { - if (type == null) { - throw new IllegalArgumentException("Type can not be null"); - } - this.type = type; - this.formula = Boolean.FALSE; - } - - public CellDataTypeEnum getType() { - return type; - } - - public void setType(CellDataTypeEnum type) { - this.type = type; - } - - public BigDecimal getNumberValue() { - return numberValue; - } - - public void setNumberValue(BigDecimal numberValue) { - this.numberValue = numberValue; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public Boolean getBooleanValue() { - return booleanValue; - } - - public void setBooleanValue(Boolean booleanValue) { - this.booleanValue = booleanValue; - } - - public Boolean getFormula() { - return formula; - } - - public void setFormula(Boolean formula) { - this.formula = formula; - } - - public String getFormulaValue() { - return formulaValue; - } - - public void setFormulaValue(String formulaValue) { - this.formulaValue = formulaValue; - } - - public byte[] getImageValue() { - return imageValue; - } - - public void setImageValue(byte[] imageValue) { - this.imageValue = imageValue; - } - - public Integer getDataFormat() { - return dataFormat; - } - - public void setDataFormat(Integer dataFormat) { - this.dataFormat = dataFormat; - } - - public String getDataFormatString() { - return dataFormatString; - } - - public void setDataFormatString(String dataFormatString) { - this.dataFormatString = dataFormatString; - } - - public T getData() { - return data; - } - - public void setData(T data) { - this.data = data; - } - - /** - * Ensure that the object does not appear null - */ - public void checkEmpty() { - if (type == null) { - type = CellDataTypeEnum.EMPTY; - } - switch (type) { - case STRING: - case ERROR: - if (StringUtils.isEmpty(stringValue)) { - type = CellDataTypeEnum.EMPTY; - } - return; - case NUMBER: - if (numberValue == null) { - type = CellDataTypeEnum.EMPTY; - } - return; - case BOOLEAN: - if (booleanValue == null) { - type = CellDataTypeEnum.EMPTY; - } - return; - default: - } - } - - public static CellData newEmptyInstance() { - return newEmptyInstance(null, null); - } - - public static CellData newEmptyInstance(Integer rowIndex, Integer columnIndex) { - CellData cellData = new CellData(CellDataTypeEnum.EMPTY); - cellData.setRowIndex(rowIndex); - cellData.setColumnIndex(columnIndex); - return cellData; - } - - public static CellData newInstance(Boolean booleanValue) { - return newInstance(booleanValue, null, null); - } - - public static CellData newInstance(Boolean booleanValue, Integer rowIndex, Integer columnIndex) { - CellData cellData = new CellData(booleanValue); - cellData.setRowIndex(rowIndex); - cellData.setColumnIndex(columnIndex); - return cellData; - } - - public static CellData newInstance(String stringValue, Integer rowIndex, Integer columnIndex) { - CellData cellData = new CellData(stringValue); - cellData.setRowIndex(rowIndex); - cellData.setColumnIndex(columnIndex); - return cellData; - } - - public static CellData newInstance(BigDecimal numberValue, Integer rowIndex, Integer columnIndex) { - CellData cellData = new CellData(numberValue); - cellData.setRowIndex(rowIndex); - cellData.setColumnIndex(columnIndex); - return cellData; - } - - @Override - public String toString() { - if (type == null) { - return StringUtils.EMPTY; - } - switch (type) { - case NUMBER: - return numberValue.toString(); - case BOOLEAN: - return booleanValue.toString(); - case DIRECT_STRING: - case STRING: - case ERROR: - return stringValue; - case IMAGE: - return "image[" + imageValue.length + "]"; - default: - return StringUtils.EMPTY; - } - } - -} diff --git a/src/main/java/com/alibaba/excel/metadata/CellExtra.java b/src/main/java/com/alibaba/excel/metadata/CellExtra.java index 937b9ac7..778f95fc 100644 --- a/src/main/java/com/alibaba/excel/metadata/CellExtra.java +++ b/src/main/java/com/alibaba/excel/metadata/CellExtra.java @@ -20,19 +20,19 @@ public class CellExtra extends AbstractCell { */ private String text; /** - * First row index,if this object is an interval + * First row index, if this object is an interval */ private Integer firstRowIndex; /** - * Last row index,if this object is an interval + * Last row index, if this object is an interval */ private Integer lastRowIndex; /** - * First column index,if this object is an interval + * First column index, if this object is an interval */ private Integer firstColumnIndex; /** - * Last column index,if this object is an interval + * Last column index, if this object is an interval */ private Integer lastColumnIndex; diff --git a/src/main/java/com/alibaba/excel/metadata/CellRange.java b/src/main/java/com/alibaba/excel/metadata/CellRange.java index 6805526e..bd0f54f9 100644 --- a/src/main/java/com/alibaba/excel/metadata/CellRange.java +++ b/src/main/java/com/alibaba/excel/metadata/CellRange.java @@ -1,8 +1,11 @@ package com.alibaba.excel.metadata; +import lombok.Data; + /** * @author jipengfei */ +@Data public class CellRange { private int firstRow; @@ -16,36 +19,4 @@ public class CellRange { this.firstCol = firstCol; this.lastCol = lastCol; } - - public int getFirstRow() { - return firstRow; - } - - public void setFirstRow(int firstRow) { - this.firstRow = firstRow; - } - - public int getLastRow() { - return lastRow; - } - - public void setLastRow(int lastRow) { - this.lastRow = lastRow; - } - - public int getFirstCol() { - return firstCol; - } - - public void setFirstCol(int firstCol) { - this.firstCol = firstCol; - } - - public int getLastCol() { - return lastCol; - } - - public void setLastCol(int lastCol) { - this.lastCol = lastCol; - } } diff --git a/src/main/java/com/alibaba/excel/metadata/ConfigurationHolder.java b/src/main/java/com/alibaba/excel/metadata/ConfigurationHolder.java index d84b1d58..ee4d7edf 100644 --- a/src/main/java/com/alibaba/excel/metadata/ConfigurationHolder.java +++ b/src/main/java/com/alibaba/excel/metadata/ConfigurationHolder.java @@ -32,5 +32,5 @@ public interface ConfigurationHolder extends Holder { * * @return Converter */ - Map converterMap(); + Map> converterMap(); } diff --git a/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java b/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java index 26f3720f..987e553b 100644 --- a/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java +++ b/src/main/java/com/alibaba/excel/metadata/GlobalConfiguration.java @@ -2,11 +2,14 @@ package com.alibaba.excel.metadata; import java.util.Locale; +import lombok.Data; + /** * Global configuration * * @author Jiaju Zhuang */ +@Data public class GlobalConfiguration { /** * Automatic trim includes sheet name and content @@ -32,35 +35,10 @@ public class GlobalConfiguration { */ private Boolean useScientificFormat; - public Boolean getUse1904windowing() { - return use1904windowing; - } - - public void setUse1904windowing(Boolean use1904windowing) { - this.use1904windowing = use1904windowing; - } - - public Boolean getAutoTrim() { - return autoTrim; - } - - public void setAutoTrim(Boolean autoTrim) { - this.autoTrim = autoTrim; - } - - public Locale getLocale() { - return locale; - } - - public void setLocale(Locale locale) { - this.locale = locale; - } - - public Boolean getUseScientificFormat() { - return useScientificFormat; - } - - public void setUseScientificFormat(Boolean useScientificFormat) { - this.useScientificFormat = useScientificFormat; + public GlobalConfiguration() { + this.autoTrim = Boolean.TRUE; + this.use1904windowing = Boolean.FALSE; + this.locale = Locale.getDefault(); + this.useScientificFormat = Boolean.FALSE; } } diff --git a/src/main/java/com/alibaba/excel/metadata/Head.java b/src/main/java/com/alibaba/excel/metadata/Head.java index c578cbbc..c150fe02 100644 --- a/src/main/java/com/alibaba/excel/metadata/Head.java +++ b/src/main/java/com/alibaba/excel/metadata/Head.java @@ -3,6 +3,7 @@ package com.alibaba.excel.metadata; import java.util.ArrayList; import java.util.List; +import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.metadata.property.ColumnWidthProperty; import com.alibaba.excel.metadata.property.FontProperty; import com.alibaba.excel.metadata.property.LoopMergeProperty; @@ -64,9 +65,15 @@ public class Head { this.columnIndex = columnIndex; this.fieldName = fieldName; if (headNameList == null) { - headNameList = new ArrayList(); + this.headNameList = new ArrayList<>(); + } else { + this.headNameList = headNameList; + for (String headName : headNameList) { + if (headName == null) { + throw new ExcelGenerateException("head name can not be null."); + } + } } - this.headNameList = headNameList; this.forceIndex = forceIndex; this.forceName = forceName; } diff --git a/src/main/java/com/alibaba/excel/metadata/NullObject.java b/src/main/java/com/alibaba/excel/metadata/NullObject.java new file mode 100644 index 00000000..845d98a1 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/NullObject.java @@ -0,0 +1,9 @@ +package com.alibaba.excel.metadata; + +/** + * Null object. + * + * @author Jiaju Zhuang + */ +public class NullObject { +} diff --git a/src/main/java/com/alibaba/excel/metadata/Sheet.java b/src/main/java/com/alibaba/excel/metadata/Sheet.java deleted file mode 100644 index 38bd30af..00000000 --- a/src/main/java/com/alibaba/excel/metadata/Sheet.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.alibaba.excel.metadata; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * - * @author jipengfei - * @deprecated pleas use {@link com.alibaba.excel.write.metadata.WriteSheet} or - * {@link com.alibaba.excel.read.metadata.ReadSheet} - */ -@Deprecated -public class Sheet { - - /** - */ - private int headLineMun; - - /** - * Starting from 1 - */ - private int sheetNo; - - /** - */ - private String sheetName; - - /** - */ - private Class clazz; - - /** - */ - private List> head; - - /** - * - */ - private TableStyle tableStyle; - - /** - * column with - */ - private Map columnWidthMap = new HashMap(); - - /** - * - */ - private Boolean autoWidth = Boolean.FALSE; - - /** - * - */ - private int startRow = 0; - - public Sheet(int sheetNo) { - this.sheetNo = sheetNo; - } - - public Sheet(int sheetNo, int headLineMun) { - this.sheetNo = sheetNo; - this.headLineMun = headLineMun; - } - - public Sheet(int sheetNo, int headLineMun, Class clazz) { - this.sheetNo = sheetNo; - this.headLineMun = headLineMun; - this.clazz = clazz; - } - - public Sheet(int sheetNo, int headLineMun, Class clazz, String sheetName, - List> head) { - this.sheetNo = sheetNo; - this.clazz = clazz; - this.headLineMun = headLineMun; - this.sheetName = sheetName; - this.head = head; - } - - public List> getHead() { - return head; - } - - public void setHead(List> head) { - this.head = head; - } - - public Class getClazz() { - return clazz; - } - - public void setClazz(Class clazz) { - this.clazz = clazz; - if (headLineMun == 0) { - this.headLineMun = 1; - } - } - - public int getHeadLineMun() { - return headLineMun; - } - - public void setHeadLineMun(int headLineMun) { - this.headLineMun = headLineMun; - } - - public int getSheetNo() { - return sheetNo; - } - - public void setSheetNo(int sheetNo) { - this.sheetNo = sheetNo; - } - - public String getSheetName() { - return sheetName; - } - - public void setSheetName(String sheetName) { - this.sheetName = sheetName; - } - - public TableStyle getTableStyle() { - return tableStyle; - } - - public void setTableStyle(TableStyle tableStyle) { - this.tableStyle = tableStyle; - } - - public Map getColumnWidthMap() { - return columnWidthMap; - } - - public void setColumnWidthMap(Map columnWidthMap) { - this.columnWidthMap = columnWidthMap; - } - - @Override - public String toString() { - return "Sheet{" + "headLineMun=" + headLineMun + ", sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' - + ", clazz=" + clazz + ", head=" + head + ", tableStyle=" + tableStyle + ", columnWidthMap=" - + columnWidthMap + '}'; - } - - public Boolean getAutoWidth() { - return autoWidth; - } - - public void setAutoWidth(Boolean autoWidth) { - this.autoWidth = autoWidth; - } - - public int getStartRow() { - return startRow; - } - - public void setStartRow(int startRow) { - this.startRow = startRow; - } -} diff --git a/src/main/java/com/alibaba/excel/metadata/Table.java b/src/main/java/com/alibaba/excel/metadata/Table.java deleted file mode 100644 index d4c63aba..00000000 --- a/src/main/java/com/alibaba/excel/metadata/Table.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.alibaba.excel.metadata; - -import java.util.List; - -/** - * @author jipengfei - * @deprecated please use {@link com.alibaba.excel.write.metadata.WriteTable} - */ -@Deprecated -public class Table { - /** - */ - private Class clazz; - - /** - */ - private List> head; - - /** - */ - private int tableNo; - - /** - */ - private TableStyle tableStyle; - - public Table(Integer tableNo) { - this.tableNo = tableNo; - } - - public TableStyle getTableStyle() { - return tableStyle; - } - - public void setTableStyle(TableStyle tableStyle) { - this.tableStyle = tableStyle; - } - - public Class getClazz() { - return clazz; - } - - public void setClazz(Class clazz) { - this.clazz = clazz; - } - - public List> getHead() { - return head; - } - - public void setHead(List> head) { - this.head = head; - } - - public int getTableNo() { - return tableNo; - } - - public void setTableNo(int tableNo) { - this.tableNo = tableNo; - } -} diff --git a/src/main/java/com/alibaba/excel/metadata/TableStyle.java b/src/main/java/com/alibaba/excel/metadata/TableStyle.java deleted file mode 100644 index fa8905c5..00000000 --- a/src/main/java/com/alibaba/excel/metadata/TableStyle.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.alibaba.excel.metadata; - -import org.apache.poi.ss.usermodel.IndexedColors; - -import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; - -/** - * @author jipengfei - * @deprecated please use {@link HorizontalCellStyleStrategy} - */ -@Deprecated -public class TableStyle { - - /** - * 表头背景颜色 - */ - private IndexedColors tableHeadBackGroundColor; - - /** - * 表头字体样式 - */ - private Font tableHeadFont; - - /** - * 表格内容字体样式 - */ - private Font tableContentFont; - - /** - * 表格内容背景颜色 - */ - private IndexedColors tableContentBackGroundColor; - - public IndexedColors getTableHeadBackGroundColor() { - return tableHeadBackGroundColor; - } - - public void setTableHeadBackGroundColor(IndexedColors tableHeadBackGroundColor) { - this.tableHeadBackGroundColor = tableHeadBackGroundColor; - } - - public Font getTableHeadFont() { - return tableHeadFont; - } - - public void setTableHeadFont(Font tableHeadFont) { - this.tableHeadFont = tableHeadFont; - } - - public Font getTableContentFont() { - return tableContentFont; - } - - public void setTableContentFont(Font tableContentFont) { - this.tableContentFont = tableContentFont; - } - - public IndexedColors getTableContentBackGroundColor() { - return tableContentBackGroundColor; - } - - public void setTableContentBackGroundColor(IndexedColors tableContentBackGroundColor) { - this.tableContentBackGroundColor = tableContentBackGroundColor; - } -} diff --git a/src/main/java/com/alibaba/excel/metadata/csv/CsvCell.java b/src/main/java/com/alibaba/excel/metadata/csv/CsvCell.java new file mode 100644 index 00000000..f0e925e6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/csv/CsvCell.java @@ -0,0 +1,354 @@ +package com.alibaba.excel.metadata.csv; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Calendar; +import java.util.Date; + +import com.alibaba.excel.enums.NumericCellTypeEnum; +import com.alibaba.excel.metadata.data.FormulaData; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.usermodel.CellBase; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +/** + * csv cell + * + * @author Jiaju Zhuang + */ +@Data +public class CsvCell extends CellBase { + + /** + * column index + */ + @Getter(value = AccessLevel.NONE) + @Setter(value = AccessLevel.NONE) + private Integer columnIndex; + + /** + * cell type + */ + @Getter(value = AccessLevel.NONE) + @Setter(value = AccessLevel.NONE) + private CellType cellType; + + /** + * numeric cell type + */ + private NumericCellTypeEnum numericCellType; + + /** + * workbook + */ + private final CsvWorkbook csvWorkbook; + + /** + * sheet + */ + private final CsvSheet csvSheet; + + /** + * row + */ + private final CsvRow csvRow; + + /** + * {@link CellType#NUMERIC} + */ + private BigDecimal numberValue; + /** + * {@link CellType#STRING} and {@link CellType#ERROR} {@link CellType#FORMULA} + */ + private String stringValue; + /** + * {@link CellType#BOOLEAN} + */ + private Boolean booleanValue; + + /** + * {@link CellType#NUMERIC} + */ + private LocalDateTime dateValue; + + /** + * formula + */ + private FormulaData formulaData; + + /** + * rich text string + */ + private RichTextString richTextString; + + /** + * style + */ + private CellStyle cellStyle; + + public CsvCell(CsvWorkbook csvWorkbook, CsvSheet csvSheet, CsvRow csvRow, Integer columnIndex, CellType cellType) { + this.csvWorkbook = csvWorkbook; + this.csvSheet = csvSheet; + this.csvRow = csvRow; + this.columnIndex = columnIndex; + this.cellType = cellType; + if (this.cellType == null) { + this.cellType = CellType._NONE; + } + } + + @Override + protected void setCellTypeImpl(CellType cellType) { + this.cellType = cellType; + } + + @Override + protected void setCellFormulaImpl(String formula) { + FormulaData formulaData = new FormulaData(); + formulaData.setFormulaValue(formula); + this.formulaData = formulaData; + this.cellType = CellType.FORMULA; + } + + @Override + protected void removeFormulaImpl() { + this.formulaData = null; + } + + @Override + protected void setCellValueImpl(double value) { + numberValue = BigDecimal.valueOf(value); + this.cellType = CellType.NUMERIC; + } + + @Override + protected void setCellValueImpl(Date value) { + if (value == null) { + return; + } + this.dateValue = LocalDateTime.ofInstant(value.toInstant(), ZoneId.systemDefault()); + this.cellType = CellType.NUMERIC; + this.numericCellType = NumericCellTypeEnum.DATE; + } + + @Override + protected void setCellValueImpl(LocalDateTime value) { + this.dateValue = value; + this.cellType = CellType.NUMERIC; + this.numericCellType = NumericCellTypeEnum.DATE; + } + + @Override + protected void setCellValueImpl(Calendar value) { + if (value == null) { + return; + } + this.dateValue = LocalDateTime.ofInstant(value.toInstant(), ZoneId.systemDefault()); + this.cellType = CellType.NUMERIC; + } + + @Override + protected void setCellValueImpl(String value) { + this.stringValue = value; + this.cellType = CellType.STRING; + } + + @Override + protected void setCellValueImpl(RichTextString value) { + richTextString = value; + this.cellType = CellType.STRING; + } + + @Override + public void setCellValue(String value) { + if (value == null) { + setBlank(); + return; + } + setCellValueImpl(value); + } + + @Override + public void setCellValue(RichTextString value) { + if (value == null || value.getString() == null) { + setBlank(); + return; + } + setCellValueImpl(value); + } + + @Override + protected SpreadsheetVersion getSpreadsheetVersion() { + return null; + } + + @Override + public int getColumnIndex() { + return columnIndex; + } + + @Override + public int getRowIndex() { + return csvRow.getRowNum(); + } + + @Override + public Sheet getSheet() { + return csvRow.getSheet(); + } + + @Override + public Row getRow() { + return csvRow; + } + + @Override + public CellType getCellType() { + return cellType; + } + + @Override + public CellType getCachedFormulaResultType() { + return getCellType(); + } + + @Override + public CellType getCachedFormulaResultTypeEnum() { + return getCellType(); + } + + @Override + public String getCellFormula() { + if (formulaData == null) { + return null; + } + return formulaData.getFormulaValue(); + } + + @Override + public double getNumericCellValue() { + if (numberValue == null) { + return 0; + } + return numberValue.doubleValue(); + } + + @Override + public Date getDateCellValue() { + if (dateValue == null) { + return null; + } + return Date.from(dateValue.atZone(ZoneId.systemDefault()).toInstant()); + } + + @Override + public LocalDateTime getLocalDateTimeCellValue() { + return dateValue; + } + + @Override + public RichTextString getRichStringCellValue() { + return richTextString; + } + + @Override + public String getStringCellValue() { + return stringValue; + } + + @Override + public void setCellValue(boolean value) { + this.booleanValue = value; + this.cellType = CellType.BOOLEAN; + } + + @Override + public void setCellErrorValue(byte value) { + this.numberValue = BigDecimal.valueOf(value); + this.cellType = CellType.ERROR; + } + + @Override + public boolean getBooleanCellValue() { + if (booleanValue == null) { + return false; + } + return booleanValue; + } + + @Override + public byte getErrorCellValue() { + if (numberValue == null) { + return 0; + } + return numberValue.byteValue(); + } + + @Override + public void setCellStyle(CellStyle style) { + this.cellStyle = style; + } + + @Override + public CellStyle getCellStyle() { + return cellStyle; + } + + @Override + public void setAsActiveCell() { + + } + + @Override + public void setCellComment(Comment comment) { + + } + + @Override + public Comment getCellComment() { + return null; + } + + @Override + public void removeCellComment() { + + } + + @Override + public Hyperlink getHyperlink() { + return null; + } + + @Override + public void setHyperlink(Hyperlink link) { + + } + + @Override + public void removeHyperlink() { + + } + + @Override + public CellRangeAddress getArrayFormulaRange() { + return null; + } + + @Override + public boolean isPartOfArrayFormulaGroup() { + return false; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/csv/CsvCellStyle.java b/src/main/java/com/alibaba/excel/metadata/csv/CsvCellStyle.java new file mode 100644 index 00000000..08b46e3a --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/csv/CsvCellStyle.java @@ -0,0 +1,333 @@ +package com.alibaba.excel.metadata.csv; + +import com.alibaba.excel.metadata.data.DataFormatData; + +import lombok.Data; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Color; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.VerticalAlignment; + +/** + * csv cell style + * + * @author Jiaju Zhuang + */ +@Data +public class CsvCellStyle implements CellStyle { + + /** + * data format + */ + private DataFormatData dataFormatData; + + /** + * index + */ + private Short index; + + public CsvCellStyle(Short index) { + this.index = index; + } + + @Override + public short getIndex() { + return index; + } + + @Override + public void setDataFormat(short fmt) { + initDataFormatData(); + dataFormatData.setIndex(fmt); + } + + private void initDataFormatData() { + if (dataFormatData == null) { + dataFormatData = new DataFormatData(); + } + } + + @Override + public short getDataFormat() { + if (dataFormatData == null) { + return 0; + } + return dataFormatData.getIndex(); + } + + @Override + public String getDataFormatString() { + if (dataFormatData == null) { + return null; + } + return dataFormatData.getFormat(); + } + + @Override + public void setFont(Font font) { + + } + + @Override + public short getFontIndex() { + return 0; + } + + @Override + public int getFontIndexAsInt() { + return 0; + } + + @Override + public void setHidden(boolean hidden) { + + } + + @Override + public boolean getHidden() { + return false; + } + + @Override + public void setLocked(boolean locked) { + + } + + @Override + public boolean getLocked() { + return false; + } + + @Override + public void setQuotePrefixed(boolean quotePrefix) { + + } + + @Override + public boolean getQuotePrefixed() { + return false; + } + + @Override + public void setAlignment(HorizontalAlignment align) { + + } + + @Override + public HorizontalAlignment getAlignment() { + return null; + } + + @Override + public HorizontalAlignment getAlignmentEnum() { + return null; + } + + @Override + public void setWrapText(boolean wrapped) { + + } + + @Override + public boolean getWrapText() { + return false; + } + + @Override + public void setVerticalAlignment(VerticalAlignment align) { + + } + + @Override + public VerticalAlignment getVerticalAlignment() { + return null; + } + + @Override + public VerticalAlignment getVerticalAlignmentEnum() { + return null; + } + + @Override + public void setRotation(short rotation) { + + } + + @Override + public short getRotation() { + return 0; + } + + @Override + public void setIndention(short indent) { + + } + + @Override + public short getIndention() { + return 0; + } + + @Override + public void setBorderLeft(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderLeft() { + return null; + } + + @Override + public BorderStyle getBorderLeftEnum() { + return null; + } + + @Override + public void setBorderRight(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderRight() { + return null; + } + + @Override + public BorderStyle getBorderRightEnum() { + return null; + } + + @Override + public void setBorderTop(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderTop() { + return null; + } + + @Override + public BorderStyle getBorderTopEnum() { + return null; + } + + @Override + public void setBorderBottom(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderBottom() { + return null; + } + + @Override + public BorderStyle getBorderBottomEnum() { + return null; + } + + @Override + public void setLeftBorderColor(short color) { + + } + + @Override + public short getLeftBorderColor() { + return 0; + } + + @Override + public void setRightBorderColor(short color) { + + } + + @Override + public short getRightBorderColor() { + return 0; + } + + @Override + public void setTopBorderColor(short color) { + + } + + @Override + public short getTopBorderColor() { + return 0; + } + + @Override + public void setBottomBorderColor(short color) { + + } + + @Override + public short getBottomBorderColor() { + return 0; + } + + @Override + public void setFillPattern(FillPatternType fp) { + + } + + @Override + public FillPatternType getFillPattern() { + return null; + } + + @Override + public FillPatternType getFillPatternEnum() { + return null; + } + + @Override + public void setFillBackgroundColor(short bg) { + + } + + @Override + public short getFillBackgroundColor() { + return 0; + } + + @Override + public Color getFillBackgroundColorColor() { + return null; + } + + @Override + public void setFillForegroundColor(short bg) { + + } + + @Override + public short getFillForegroundColor() { + return 0; + } + + @Override + public Color getFillForegroundColorColor() { + return null; + } + + @Override + public void cloneStyleFrom(CellStyle source) { + + } + + @Override + public void setShrinkToFit(boolean shrinkToFit) { + + } + + @Override + public boolean getShrinkToFit() { + return false; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/csv/CsvDataFormat.java b/src/main/java/com/alibaba/excel/metadata/csv/CsvDataFormat.java new file mode 100644 index 00000000..42d3f043 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/csv/CsvDataFormat.java @@ -0,0 +1,65 @@ +package com.alibaba.excel.metadata.csv; + +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import com.alibaba.excel.constant.BuiltinFormats; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.excel.util.MapUtils; + +import org.apache.poi.ss.usermodel.DataFormat; + +/** + * format data + * + * @author Jiaju Zhuang + */ +public class CsvDataFormat implements DataFormat { + /** + * It is stored in both map and list for easy retrieval + */ + private final Map formatMap; + private final List formatList; + + /** + * Excel's built-in format conversion. + */ + private final Map builtinFormatsMap; + private final String[] builtinFormats; + + public CsvDataFormat(Locale locale) { + formatMap = MapUtils.newHashMap(); + formatList = ListUtils.newArrayList(); + builtinFormatsMap = BuiltinFormats.switchBuiltinFormatsMap(locale); + builtinFormats = BuiltinFormats.switchBuiltinFormats(locale); + } + + @Override + public short getFormat(String format) { + Short index = builtinFormatsMap.get(format); + if (index != null) { + return index; + } + index = formatMap.get(format); + if (index != null) { + return index; + } + index = (short)(formatList.size() + BuiltinFormats.MIN_CUSTOM_DATA_FORMAT_INDEX); + formatList.add(format); + formatMap.put(format, index); + return index; + } + + @Override + public String getFormat(short index) { + if (index < BuiltinFormats.MIN_CUSTOM_DATA_FORMAT_INDEX) { + return builtinFormats[index]; + } + int actualIndex = index - BuiltinFormats.MIN_CUSTOM_DATA_FORMAT_INDEX; + if (actualIndex < formatList.size()) { + return formatList.get(actualIndex); + } + return null; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/csv/CsvRichTextString.java b/src/main/java/com/alibaba/excel/metadata/csv/CsvRichTextString.java new file mode 100644 index 00000000..1c54b0c3 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/csv/CsvRichTextString.java @@ -0,0 +1,68 @@ +package com.alibaba.excel.metadata.csv; + +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.RichTextString; + +/** + * rich text string + * + * @author Jiaju Zhuang + */ +public class CsvRichTextString implements RichTextString { + /** + * string + */ + private final String string; + + public CsvRichTextString(String string) { + this.string = string; + } + + @Override + public void applyFont(int startIndex, int endIndex, short fontIndex) { + + } + + @Override + public void applyFont(int startIndex, int endIndex, Font font) { + + } + + @Override + public void applyFont(Font font) { + + } + + @Override + public void clearFormatting() { + + } + + @Override + public String getString() { + return string; + } + + @Override + public int length() { + if (string == null) { + return 0; + } + return string.length(); + } + + @Override + public int numFormattingRuns() { + return 0; + } + + @Override + public int getIndexOfFormattingRun(int index) { + return 0; + } + + @Override + public void applyFont(short fontIndex) { + + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/csv/CsvRow.java b/src/main/java/com/alibaba/excel/metadata/csv/CsvRow.java new file mode 100644 index 00000000..24acd9d9 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/csv/CsvRow.java @@ -0,0 +1,192 @@ +package com.alibaba.excel.metadata.csv; + +import java.util.Iterator; +import java.util.List; + +import lombok.Data; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.compress.utils.Lists; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; + +/** + * csv row + * + * @author Jiaju Zhuang + */ +@Data +public class CsvRow implements Row { + + /** + * cell list + */ + private final List cellList; + + /** + * workbook + */ + private final CsvWorkbook csvWorkbook; + + /** + * sheet + */ + private final CsvSheet csvSheet; + + /** + * row index + */ + private Integer rowIndex; + + /** + * style + */ + private CellStyle cellStyle; + + public CsvRow(CsvWorkbook csvWorkbook, CsvSheet csvSheet, Integer rowIndex) { + cellList = Lists.newArrayList(); + this.csvWorkbook = csvWorkbook; + this.csvSheet = csvSheet; + this.rowIndex = rowIndex; + } + + @Override + public Cell createCell(int column) { + CsvCell cell = new CsvCell(csvWorkbook, csvSheet, this, column, null); + cellList.add(cell); + return cell; + } + + @Override + public Cell createCell(int column, CellType type) { + CsvCell cell = new CsvCell(csvWorkbook, csvSheet, this, column, type); + cellList.add(cell); + return cell; + } + + @Override + public void removeCell(Cell cell) { + cellList.remove(cell); + } + + @Override + public void setRowNum(int rowNum) { + this.rowIndex = rowNum; + } + + @Override + public int getRowNum() { + return rowIndex; + } + + @Override + public Cell getCell(int cellnum) { + if (cellnum >= cellList.size()) { + return null; + } + return cellList.get(cellnum - 1); + } + + @Override + public Cell getCell(int cellnum, MissingCellPolicy policy) { + return getCell(cellnum); + } + + @Override + public short getFirstCellNum() { + if (CollectionUtils.isEmpty(cellList)) { + return -1; + } + return 0; + } + + @Override + public short getLastCellNum() { + if (CollectionUtils.isEmpty(cellList)) { + return -1; + } + return (short)cellList.size(); + } + + @Override + public int getPhysicalNumberOfCells() { + return getRowNum(); + } + + @Override + public void setHeight(short height) { + + } + + @Override + public void setZeroHeight(boolean zHeight) { + + } + + @Override + public boolean getZeroHeight() { + return false; + } + + @Override + public void setHeightInPoints(float height) { + + } + + @Override + public short getHeight() { + return 0; + } + + @Override + public float getHeightInPoints() { + return 0; + } + + @Override + public boolean isFormatted() { + return false; + } + + @Override + public CellStyle getRowStyle() { + return cellStyle; + } + + @Override + public void setRowStyle(CellStyle style) { + this.cellStyle = style; + } + + @Override + public Iterator cellIterator() { + return (Iterator)(Iterator)cellList.iterator(); + } + + @Override + public Sheet getSheet() { + return csvSheet; + } + + @Override + public int getOutlineLevel() { + return 0; + } + + @Override + public void shiftCellsRight(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { + + } + + @Override + public void shiftCellsLeft(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { + + } + + @Override + public Iterator iterator() { + return cellIterator(); + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/csv/CsvSheet.java b/src/main/java/com/alibaba/excel/metadata/csv/CsvSheet.java new file mode 100644 index 00000000..b002b6b4 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/csv/CsvSheet.java @@ -0,0 +1,801 @@ +package com.alibaba.excel.metadata.csv; + +import java.io.Closeable; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.alibaba.excel.constant.BuiltinFormats; +import com.alibaba.excel.enums.NumericCellTypeEnum; +import com.alibaba.excel.exception.ExcelGenerateException; +import com.alibaba.excel.util.DateUtils; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.excel.util.NumberDataFormatterUtils; +import com.alibaba.excel.util.StringUtils; + +import lombok.Data; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.poi.ss.usermodel.AutoFilter; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellRange; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Footer; +import org.apache.poi.ss.usermodel.Header; +import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.usermodel.PrintSetup; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.SheetConditionalFormatting; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellAddress; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.PaneInformation; + +/** + * csv sheet + * + * @author Jiaju Zhuang + */ +@Data +public class CsvSheet implements Sheet, Closeable { + /** + * workbook + */ + private CsvWorkbook csvWorkbook; + /** + * output + */ + private Appendable out; + /** + * row cache + */ + private Integer rowCacheCount; + /** + * format + */ + public CSVFormat csvFormat; + + /** + * last row index + */ + private Integer lastRowIndex; + + /** + * row cache + */ + private List rowCache; + /** + * csv printer + */ + private CSVPrinter csvPrinter; + + public CsvSheet(CsvWorkbook csvWorkbook, Appendable out) { + this.csvWorkbook = csvWorkbook; + this.out = out; + this.rowCacheCount = 3000; + this.csvFormat = CSVFormat.DEFAULT; + this.lastRowIndex = -1; + } + + @Override + public Row createRow(int rownum) { + // Initialize the data when the row is first created + initSheet(); + + lastRowIndex++; + assert rownum == lastRowIndex : "csv create row must be in order."; + printData(); + CsvRow csvRow = new CsvRow(csvWorkbook, this, rownum); + rowCache.add(csvRow); + return csvRow; + } + + private void initSheet() { + if (csvPrinter != null) { + return; + } + rowCache = ListUtils.newArrayListWithExpectedSize(rowCacheCount); + try { + csvPrinter = csvFormat.print(out); + } catch (IOException e) { + throw new ExcelGenerateException(e); + } + } + + @Override + public void removeRow(Row row) { + throw new UnsupportedOperationException("csv cannot move row."); + } + + @Override + public Row getRow(int rownum) { + int actualRowIndex = rownum - (lastRowIndex - rowCache.size()) - 1; + if (actualRowIndex < 0 || actualRowIndex > rowCache.size() - 1) { + throw new UnsupportedOperationException("The current data does not exist or has been flushed to disk\n."); + } + return rowCache.get(actualRowIndex); + } + + @Override + public int getPhysicalNumberOfRows() { + return lastRowIndex - rowCache.size(); + } + + @Override + public int getFirstRowNum() { + if (lastRowIndex < 0) { + return -1; + } + return 0; + } + + @Override + public int getLastRowNum() { + return lastRowIndex; + } + + @Override + public void setColumnHidden(int columnIndex, boolean hidden) { + + } + + @Override + public boolean isColumnHidden(int columnIndex) { + return false; + } + + @Override + public void setRightToLeft(boolean value) { + + } + + @Override + public boolean isRightToLeft() { + return false; + } + + @Override + public void setColumnWidth(int columnIndex, int width) { + + } + + @Override + public int getColumnWidth(int columnIndex) { + return 0; + } + + @Override + public float getColumnWidthInPixels(int columnIndex) { + return 0; + } + + @Override + public void setDefaultColumnWidth(int width) { + + } + + @Override + public int getDefaultColumnWidth() { + return 0; + } + + @Override + public short getDefaultRowHeight() { + return 0; + } + + @Override + public float getDefaultRowHeightInPoints() { + return 0; + } + + @Override + public void setDefaultRowHeight(short height) { + + } + + @Override + public void setDefaultRowHeightInPoints(float height) { + + } + + @Override + public CellStyle getColumnStyle(int column) { + return null; + } + + @Override + public int addMergedRegion(CellRangeAddress region) { + return 0; + } + + @Override + public int addMergedRegionUnsafe(CellRangeAddress region) { + return 0; + } + + @Override + public void validateMergedRegions() { + + } + + @Override + public void setVerticallyCenter(boolean value) { + + } + + @Override + public void setHorizontallyCenter(boolean value) { + + } + + @Override + public boolean getHorizontallyCenter() { + return false; + } + + @Override + public boolean getVerticallyCenter() { + return false; + } + + @Override + public void removeMergedRegion(int index) { + + } + + @Override + public void removeMergedRegions(Collection indices) { + + } + + @Override + public int getNumMergedRegions() { + return 0; + } + + @Override + public CellRangeAddress getMergedRegion(int index) { + return null; + } + + @Override + public List getMergedRegions() { + return null; + } + + @Override + public Iterator rowIterator() { + return (Iterator)(Iterator)rowCache.iterator(); + } + + @Override + public void setForceFormulaRecalculation(boolean value) { + + } + + @Override + public boolean getForceFormulaRecalculation() { + return false; + } + + @Override + public void setAutobreaks(boolean value) { + + } + + @Override + public void setDisplayGuts(boolean value) { + + } + + @Override + public void setDisplayZeros(boolean value) { + + } + + @Override + public boolean isDisplayZeros() { + return false; + } + + @Override + public void setFitToPage(boolean value) { + + } + + @Override + public void setRowSumsBelow(boolean value) { + + } + + @Override + public void setRowSumsRight(boolean value) { + + } + + @Override + public boolean getAutobreaks() { + return false; + } + + @Override + public boolean getDisplayGuts() { + return false; + } + + @Override + public boolean getFitToPage() { + return false; + } + + @Override + public boolean getRowSumsBelow() { + return false; + } + + @Override + public boolean getRowSumsRight() { + return false; + } + + @Override + public boolean isPrintGridlines() { + return false; + } + + @Override + public void setPrintGridlines(boolean show) { + + } + + @Override + public boolean isPrintRowAndColumnHeadings() { + return false; + } + + @Override + public void setPrintRowAndColumnHeadings(boolean show) { + + } + + @Override + public PrintSetup getPrintSetup() { + return null; + } + + @Override + public Header getHeader() { + return null; + } + + @Override + public Footer getFooter() { + return null; + } + + @Override + public void setSelected(boolean value) { + + } + + @Override + public double getMargin(short margin) { + return 0; + } + + @Override + public void setMargin(short margin, double size) { + + } + + @Override + public boolean getProtect() { + return false; + } + + @Override + public void protectSheet(String password) { + + } + + @Override + public boolean getScenarioProtect() { + return false; + } + + @Override + public void setZoom(int scale) { + + } + + @Override + public short getTopRow() { + return 0; + } + + @Override + public short getLeftCol() { + return 0; + } + + @Override + public void showInPane(int topRow, int leftCol) { + + } + + @Override + public void shiftRows(int startRow, int endRow, int n) { + + } + + @Override + public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { + + } + + @Override + public void shiftColumns(int startColumn, int endColumn, int n) { + + } + + @Override + public void createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) { + + } + + @Override + public void createFreezePane(int colSplit, int rowSplit) { + + } + + @Override + public void createSplitPane(int xSplitPos, int ySplitPos, int leftmostColumn, int topRow, int activePane) { + + } + + @Override + public PaneInformation getPaneInformation() { + return null; + } + + @Override + public void setDisplayGridlines(boolean show) { + + } + + @Override + public boolean isDisplayGridlines() { + return false; + } + + @Override + public void setDisplayFormulas(boolean show) { + + } + + @Override + public boolean isDisplayFormulas() { + return false; + } + + @Override + public void setDisplayRowColHeadings(boolean show) { + + } + + @Override + public boolean isDisplayRowColHeadings() { + return false; + } + + @Override + public void setRowBreak(int row) { + + } + + @Override + public boolean isRowBroken(int row) { + return false; + } + + @Override + public void removeRowBreak(int row) { + + } + + @Override + public int[] getRowBreaks() { + return new int[0]; + } + + @Override + public int[] getColumnBreaks() { + return new int[0]; + } + + @Override + public void setColumnBreak(int column) { + + } + + @Override + public boolean isColumnBroken(int column) { + return false; + } + + @Override + public void removeColumnBreak(int column) { + + } + + @Override + public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) { + + } + + @Override + public void groupColumn(int fromColumn, int toColumn) { + + } + + @Override + public void ungroupColumn(int fromColumn, int toColumn) { + + } + + @Override + public void groupRow(int fromRow, int toRow) { + + } + + @Override + public void ungroupRow(int fromRow, int toRow) { + + } + + @Override + public void setRowGroupCollapsed(int row, boolean collapse) { + + } + + @Override + public void setDefaultColumnStyle(int column, CellStyle style) { + + } + + @Override + public void autoSizeColumn(int column) { + + } + + @Override + public void autoSizeColumn(int column, boolean useMergedCells) { + + } + + @Override + public Comment getCellComment(CellAddress ref) { + return null; + } + + @Override + public Map getCellComments() { + return null; + } + + @Override + public Drawing getDrawingPatriarch() { + return null; + } + + @Override + public Drawing createDrawingPatriarch() { + return null; + } + + @Override + public Workbook getWorkbook() { + return csvWorkbook; + } + + @Override + public String getSheetName() { + return null; + } + + @Override + public boolean isSelected() { + return false; + } + + @Override + public CellRange setArrayFormula( + String formula, CellRangeAddress range) { + return null; + } + + @Override + public CellRange removeArrayFormula(Cell cell) { + return null; + } + + @Override + public DataValidationHelper getDataValidationHelper() { + return null; + } + + @Override + public List getDataValidations() { + return null; + } + + @Override + public void addValidationData(DataValidation dataValidation) { + + } + + @Override + public AutoFilter setAutoFilter(CellRangeAddress range) { + return null; + } + + @Override + public SheetConditionalFormatting getSheetConditionalFormatting() { + return null; + } + + @Override + public CellRangeAddress getRepeatingRows() { + return null; + } + + @Override + public CellRangeAddress getRepeatingColumns() { + return null; + } + + @Override + public void setRepeatingRows(CellRangeAddress rowRangeRef) { + + } + + @Override + public void setRepeatingColumns(CellRangeAddress columnRangeRef) { + + } + + @Override + public int getColumnOutlineLevel(int columnIndex) { + return 0; + } + + @Override + public Hyperlink getHyperlink(int row, int column) { + return null; + } + + @Override + public Hyperlink getHyperlink(CellAddress addr) { + return null; + } + + @Override + public List getHyperlinkList() { + return null; + } + + @Override + public CellAddress getActiveCell() { + return null; + } + + @Override + public void setActiveCell(CellAddress address) { + + } + + @Override + public Iterator iterator() { + return rowIterator(); + } + + @Override + public void close() throws IOException { + // Avoid empty sheets + initSheet(); + + flushData(); + csvPrinter.flush(); + csvPrinter.close(); + } + + public void printData() { + if (rowCache.size() >= rowCacheCount) { + flushData(); + } + } + + public void flushData() { + try { + for (CsvRow row : rowCache) { + Iterator cellIterator = row.cellIterator(); + int columnIndex = 0; + while (cellIterator.hasNext()) { + CsvCell csvCell = (CsvCell)cellIterator.next(); + while (csvCell.getColumnIndex() > columnIndex++) { + csvPrinter.print(null); + } + csvPrinter.print(buildCellValue(csvCell)); + } + csvPrinter.println(); + } + rowCache.clear(); + } catch (IOException e) { + throw new ExcelGenerateException(e); + } + } + + private String buildCellValue(CsvCell csvCell) { + switch (csvCell.getCellType()) { + case STRING: + case ERROR: + return csvCell.getStringCellValue(); + case NUMERIC: + Short dataFormat = null; + String dataFormatString = null; + if (csvCell.getCellStyle() != null) { + dataFormat = csvCell.getCellStyle().getDataFormat(); + dataFormatString = csvCell.getCellStyle().getDataFormatString(); + } + if (csvCell.getNumericCellType() == NumericCellTypeEnum.DATE) { + if (csvCell.getDateValue() == null) { + return null; + } + // date + if (dataFormat == null) { + dataFormatString = DateUtils.defaultDateFormat; + dataFormat = csvWorkbook.createDataFormat().getFormat(dataFormatString); + } + if (dataFormatString == null) { + dataFormatString = csvWorkbook.createDataFormat().getFormat(dataFormat); + } + return NumberDataFormatterUtils.format(BigDecimal.valueOf( + DateUtil.getExcelDate(csvCell.getDateValue(), csvWorkbook.getUse1904windowing())), + dataFormat, dataFormatString, csvWorkbook.getUse1904windowing(), csvWorkbook.getLocale(), + csvWorkbook.getUseScientificFormat()); + } else { + if (csvCell.getNumberValue() == null) { + return null; + } + //number + if (dataFormat == null) { + dataFormat = BuiltinFormats.GENERAL; + dataFormatString = csvWorkbook.createDataFormat().getFormat(dataFormat); + } + if (dataFormatString == null) { + dataFormatString = csvWorkbook.createDataFormat().getFormat(dataFormat); + } + return NumberDataFormatterUtils.format(csvCell.getNumberValue(), dataFormat, dataFormatString, + csvWorkbook.getUse1904windowing(), csvWorkbook.getLocale(), + csvWorkbook.getUseScientificFormat()); + } + case BOOLEAN: + return csvCell.getBooleanValue().toString(); + case BLANK: + return StringUtils.EMPTY; + default: + return null; + } + } + +} diff --git a/src/main/java/com/alibaba/excel/metadata/csv/CsvWorkbook.java b/src/main/java/com/alibaba/excel/metadata/csv/CsvWorkbook.java new file mode 100644 index 00000000..e26a2b65 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/csv/CsvWorkbook.java @@ -0,0 +1,409 @@ +package com.alibaba.excel.metadata.csv; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +import lombok.Data; +import org.apache.commons.compress.utils.Lists; +import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.formula.udf.UDFFinder; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.DataFormat; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.SheetVisibility; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * csv workbook + * + * @author Jiaju Zhuang + */ +@Data +public class CsvWorkbook implements Workbook { + /** + * output + */ + private Appendable out; + + /** + * true if date uses 1904 windowing, or false if using 1900 date windowing. + * + * default is false + * + * @return + */ + private Boolean use1904windowing; + + /** + * locale + */ + private Locale locale; + + /** + * Whether to use scientific Format. + * + * default is false + */ + private Boolean useScientificFormat; + + /** + * data format + */ + private CsvDataFormat csvDataFormat; + /** + * sheet + */ + private CsvSheet csvSheet; + /** + * cell style + */ + private List csvCellStyleList; + + public CsvWorkbook(Appendable out, Locale locale, Boolean use1904windowing, Boolean useScientificFormat) { + this.out = out; + this.locale = locale; + this.use1904windowing = use1904windowing; + this.useScientificFormat = useScientificFormat; + } + + @Override + public int getActiveSheetIndex() { + return 0; + } + + @Override + public void setActiveSheet(int sheetIndex) { + + } + + @Override + public int getFirstVisibleTab() { + return 0; + } + + @Override + public void setFirstVisibleTab(int sheetIndex) { + + } + + @Override + public void setSheetOrder(String sheetname, int pos) { + + } + + @Override + public void setSelectedTab(int index) { + + } + + @Override + public void setSheetName(int sheet, String name) { + + } + + @Override + public String getSheetName(int sheet) { + return null; + } + + @Override + public int getSheetIndex(String name) { + return 0; + } + + @Override + public int getSheetIndex(Sheet sheet) { + return 0; + } + + @Override + public Sheet createSheet() { + assert csvSheet == null : "CSV repeat creation is not allowed."; + csvSheet = new CsvSheet(this, out); + return csvSheet; + } + + @Override + public Sheet createSheet(String sheetname) { + assert csvSheet == null : "CSV repeat creation is not allowed."; + csvSheet = new CsvSheet(this, out); + return csvSheet; + } + + @Override + public Sheet cloneSheet(int sheetNum) { + return null; + } + + @Override + public Iterator sheetIterator() { + return null; + } + + @Override + public int getNumberOfSheets() { + return 0; + } + + @Override + public Sheet getSheetAt(int index) { + assert index == 0 : "CSV exists only in one sheet."; + return csvSheet; + } + + @Override + public Sheet getSheet(String name) { + return csvSheet; + } + + @Override + public void removeSheetAt(int index) { + + } + + @Override + public Font createFont() { + return null; + } + + @Override + public Font findFont(boolean bold, short color, short fontHeight, String name, boolean italic, boolean strikeout, + short typeOffset, byte underline) { + return null; + } + + @Override + public short getNumberOfFonts() { + return 0; + } + + @Override + public int getNumberOfFontsAsInt() { + return 0; + } + + @Override + public Font getFontAt(short idx) { + return null; + } + + @Override + public Font getFontAt(int idx) { + return null; + } + + @Override + public CellStyle createCellStyle() { + if (csvCellStyleList == null) { + csvCellStyleList = Lists.newArrayList(); + } + CsvCellStyle csvCellStyle = new CsvCellStyle((short)csvCellStyleList.size()); + csvCellStyleList.add(csvCellStyle); + return csvCellStyle; + } + + @Override + public int getNumCellStyles() { + return csvCellStyleList.size(); + } + + @Override + public CellStyle getCellStyleAt(int idx) { + if (idx < 0 || idx >= csvCellStyleList.size()) { + return null; + } + return csvCellStyleList.get(idx); + } + + @Override + public void write(OutputStream stream) throws IOException { + csvSheet.close(); + } + + @Override + public void close() throws IOException { + + } + + @Override + public int getNumberOfNames() { + return 0; + } + + @Override + public Name getName(String name) { + return null; + } + + @Override + public List getNames(String name) { + return null; + } + + @Override + public List getAllNames() { + return null; + } + + @Override + public Name getNameAt(int nameIndex) { + return null; + } + + @Override + public Name createName() { + return null; + } + + @Override + public int getNameIndex(String name) { + return 0; + } + + @Override + public void removeName(int index) { + + } + + @Override + public void removeName(String name) { + + } + + @Override + public void removeName(Name name) { + + } + + @Override + public int linkExternalWorkbook(String name, Workbook workbook) { + return 0; + } + + @Override + public void setPrintArea(int sheetIndex, String reference) { + + } + + @Override + public void setPrintArea(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) { + + } + + @Override + public String getPrintArea(int sheetIndex) { + return null; + } + + @Override + public void removePrintArea(int sheetIndex) { + + } + + @Override + public MissingCellPolicy getMissingCellPolicy() { + return null; + } + + @Override + public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy) { + + } + + @Override + public DataFormat createDataFormat() { + if (csvDataFormat != null) { + return csvDataFormat; + } + csvDataFormat = new CsvDataFormat(locale); + return csvDataFormat; + } + + @Override + public int addPicture(byte[] pictureData, int format) { + return 0; + } + + @Override + public List getAllPictures() { + return null; + } + + @Override + public CreationHelper getCreationHelper() { + return null; + } + + @Override + public boolean isHidden() { + return false; + } + + @Override + public void setHidden(boolean hiddenFlag) { + + } + + @Override + public boolean isSheetHidden(int sheetIx) { + return false; + } + + @Override + public boolean isSheetVeryHidden(int sheetIx) { + return false; + } + + @Override + public void setSheetHidden(int sheetIx, boolean hidden) { + + } + + @Override + public SheetVisibility getSheetVisibility(int sheetIx) { + return null; + } + + @Override + public void setSheetVisibility(int sheetIx, SheetVisibility visibility) { + + } + + @Override + public void addToolPack(UDFFinder toopack) { + + } + + @Override + public void setForceFormulaRecalculation(boolean value) { + + } + + @Override + public boolean getForceFormulaRecalculation() { + return false; + } + + @Override + public SpreadsheetVersion getSpreadsheetVersion() { + return null; + } + + @Override + public int addOlePackage(byte[] oleData, String label, String fileName, String command) throws IOException { + return 0; + } + + @Override + public Iterator iterator() { + return null; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/CellData.java b/src/main/java/com/alibaba/excel/metadata/data/CellData.java new file mode 100644 index 00000000..ed6085f9 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/CellData.java @@ -0,0 +1,76 @@ +package com.alibaba.excel.metadata.data; + +import java.math.BigDecimal; + +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.AbstractCell; +import com.alibaba.excel.util.StringUtils; + +import lombok.Data; + +/** + * Excel internal cell data. + * + *

+ * + * @author Jiaju Zhuang + */ +@Data +public class CellData extends AbstractCell { + /** + * cell type + */ + private CellDataTypeEnum type; + /** + * {@link CellDataTypeEnum#NUMBER} + */ + private BigDecimal numberValue; + /** + * {@link CellDataTypeEnum#STRING} and{@link CellDataTypeEnum#ERROR} + */ + private String stringValue; + /** + * {@link CellDataTypeEnum#BOOLEAN} + */ + private Boolean booleanValue; + + /** + * The resulting converted data. + */ + private T data; + + /** + * formula + */ + private FormulaData formulaData; + + /** + * Ensure that the object does not appear null + */ + public void checkEmpty() { + if (type == null) { + type = CellDataTypeEnum.EMPTY; + } + switch (type) { + case STRING: + case ERROR: + if (StringUtils.isEmpty(stringValue)) { + type = CellDataTypeEnum.EMPTY; + } + return; + case NUMBER: + if (numberValue == null) { + type = CellDataTypeEnum.EMPTY; + } + return; + case BOOLEAN: + if (booleanValue == null) { + type = CellDataTypeEnum.EMPTY; + } + return; + default: + } + } + + +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/ClientAnchorData.java b/src/main/java/com/alibaba/excel/metadata/data/ClientAnchorData.java new file mode 100644 index 00000000..2416635d --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/ClientAnchorData.java @@ -0,0 +1,120 @@ +package com.alibaba.excel.metadata.data; + +import lombok.Data; +import lombok.Getter; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.util.Internal; + +/** + * A client anchor is attached to an excel worksheet. It anchors against + * absolute coordinates, a top-left cell and fixed height and width, or + * a top-left and bottom-right cell, depending on the {@link ClientAnchorData.AnchorType}: + *

    + *
  1. {@link ClientAnchor.AnchorType#DONT_MOVE_AND_RESIZE} == absolute top-left coordinates and width/height, no + * cell references + *
  2. {@link ClientAnchor.AnchorType#MOVE_DONT_RESIZE} == fixed top-left cell reference, absolute width/height + *
  3. {@link ClientAnchor.AnchorType#MOVE_AND_RESIZE} == fixed top-left and bottom-right cell references, dynamic + * width/height + *
+ * Note this class only reports the current values for possibly calculated positions and sizes. + * If the sheet row/column sizes or positions shift, this needs updating via external calculations. + * + * @author Jiaju Zhuang + */ +@Data +public class ClientAnchorData extends CoordinateData { + /** + * top + */ + private Integer top; + + /** + * right + */ + private Integer right; + + /** + * bottom + */ + private Integer bottom; + + /** + * left + */ + private Integer left; + + /** + * anchor type + */ + private AnchorType anchorType; + + @Getter + public enum AnchorType { + /** + * Move and Resize With Anchor Cells (0) + *

+ * Specifies that the current drawing shall move and + * resize to maintain its row and column anchors (i.e. the + * object is anchored to the actual from and to row and column) + *

+ */ + MOVE_AND_RESIZE(ClientAnchor.AnchorType.MOVE_AND_RESIZE), + + /** + * Don't Move but do Resize With Anchor Cells (1) + *

+ * Specifies that the current drawing shall not move with its + * row and column, but should be resized. This option is not normally + * used, but is included for completeness. + *

+ * Note: Excel has no setting for this combination, nor does the ECMA standard. + */ + DONT_MOVE_DO_RESIZE(ClientAnchor.AnchorType.DONT_MOVE_DO_RESIZE), + + /** + * Move With Cells but Do Not Resize (2) + *

+ * Specifies that the current drawing shall move with its + * row and column (i.e. the object is anchored to the + * actual from row and column), but that the size shall remain absolute. + *

+ *

+ * If additional rows/columns are added between the from and to locations of the drawing, + * the drawing shall move its to anchors as needed to maintain this same absolute size. + *

+ */ + MOVE_DONT_RESIZE(ClientAnchor.AnchorType.MOVE_DONT_RESIZE), + + /** + * Do Not Move or Resize With Underlying Rows/Columns (3) + *

+ * Specifies that the current start and end positions shall + * be maintained with respect to the distances from the + * absolute start point of the worksheet. + *

+ *

+ * If additional rows/columns are added before the + * drawing, the drawing shall move its anchors as needed + * to maintain this same absolute position. + *

+ */ + DONT_MOVE_AND_RESIZE(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE); + + ClientAnchor.AnchorType value; + + AnchorType(ClientAnchor.AnchorType value) { + this.value = value; + } + + /** + * return the AnchorType corresponding to the code + * + * @param value the anchor type code + * @return the anchor type enum + */ + @Internal + public static ClientAnchorData.AnchorType byId(int value) { + return values()[value]; + } + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/CommentData.java b/src/main/java/com/alibaba/excel/metadata/data/CommentData.java new file mode 100644 index 00000000..08cff272 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/CommentData.java @@ -0,0 +1,20 @@ +package com.alibaba.excel.metadata.data; + +import lombok.Data; + +/** + * comment + * + * @author Jiaju Zhuang + */ +@Data +public class CommentData extends ClientAnchorData { + /** + * Name of the original comment author + */ + private String author; + /** + * rich text string + */ + private RichTextStringData richTextStringData; +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/CoordinateData.java b/src/main/java/com/alibaba/excel/metadata/data/CoordinateData.java new file mode 100644 index 00000000..69242e57 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/CoordinateData.java @@ -0,0 +1,45 @@ +package com.alibaba.excel.metadata.data; + +import lombok.Data; + +/** + * coordinate. + * + * @author Jiaju Zhuang + */ +@Data +public class CoordinateData { + /** + * first row index.Priority is higher than {@link #relativeFirstRowIndex}. + */ + private Integer firstRowIndex; + /** + * first column index.Priority is higher than {@link #relativeFirstColumnIndex}. + */ + private Integer firstColumnIndex; + /** + * last row index.Priority is higher than {@link #relativeLastRowIndex}. + */ + private Integer lastRowIndex; + /** + * last column index.Priority is higher than {@link #relativeLastColumnIndex}. + */ + private Integer lastColumnIndex; + + /** + * relative first row index + */ + private Integer relativeFirstRowIndex; + /** + * relative first column index + */ + private Integer relativeFirstColumnIndex; + /** + * relative last row index + */ + private Integer relativeLastRowIndex; + /** + *relative last column index + */ + private Integer relativeLastColumnIndex; +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/DataFormatData.java b/src/main/java/com/alibaba/excel/metadata/data/DataFormatData.java new file mode 100644 index 00000000..7f1a14c8 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/DataFormatData.java @@ -0,0 +1,29 @@ +package com.alibaba.excel.metadata.data; + +import lombok.Data; + +/** + * data format + * + * @author Jiaju Zhuang + */ +@Data +public class DataFormatData { + /** + * index + */ + private Short index; + + /** + * format + */ + private String format; + + @Override + public DataFormatData clone() { + DataFormatData dataFormatData = new DataFormatData(); + dataFormatData.setIndex(getIndex()); + dataFormatData.setFormat(getFormat()); + return dataFormatData; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/FormulaData.java b/src/main/java/com/alibaba/excel/metadata/data/FormulaData.java new file mode 100644 index 00000000..36d0206b --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/FormulaData.java @@ -0,0 +1,23 @@ +package com.alibaba.excel.metadata.data; + +import lombok.Data; + +/** + * formula + * + * @author Jiaju Zhuang + */ +@Data +public class FormulaData { + /** + * formula + */ + private String formulaValue; + + @Override + public FormulaData clone() { + FormulaData formulaData = new FormulaData(); + formulaData.setFormulaValue(getFormulaValue()); + return formulaData; + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/HyperlinkData.java b/src/main/java/com/alibaba/excel/metadata/data/HyperlinkData.java new file mode 100644 index 00000000..3fa23893 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/HyperlinkData.java @@ -0,0 +1,55 @@ +package com.alibaba.excel.metadata.data; + +import lombok.Data; +import lombok.Getter; + +/** + * hyperlink + * + * @author Jiaju Zhuang + */ +@Data +public class HyperlinkData extends CoordinateData { + /** + * Depending on the hyperlink type it can be URL, e-mail, path to a file, etc + */ + private String address; + /** + * hyperlink type + */ + private HyperlinkType hyperlinkType; + + @Getter + public enum HyperlinkType { + /** + * Not a hyperlink + */ + NONE(org.apache.poi.common.usermodel.HyperlinkType.NONE), + + /** + * Link to an existing file or web page + */ + URL(org.apache.poi.common.usermodel.HyperlinkType.URL), + + /** + * Link to a place in this document + */ + DOCUMENT(org.apache.poi.common.usermodel.HyperlinkType.DOCUMENT), + + /** + * Link to an E-mail address + */ + EMAIL(org.apache.poi.common.usermodel.HyperlinkType.EMAIL), + + /** + * Link to a file + */ + FILE(org.apache.poi.common.usermodel.HyperlinkType.FILE); + + org.apache.poi.common.usermodel.HyperlinkType value; + + HyperlinkType(org.apache.poi.common.usermodel.HyperlinkType value) { + this.value = value; + } + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/ImageData.java b/src/main/java/com/alibaba/excel/metadata/data/ImageData.java new file mode 100644 index 00000000..20cd43e1 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/ImageData.java @@ -0,0 +1,60 @@ +package com.alibaba.excel.metadata.data; + +import lombok.Data; +import lombok.Getter; + +/** + * image + * + * @author Jiaju Zhuang + */ +@Data +public class ImageData extends ClientAnchorData { + + /** + * image + */ + private byte[] image; + + /** + * image type + */ + private ImageType imageType; + + @Getter + public enum ImageType { + /** + * Extended windows meta file + */ + PICTURE_TYPE_EMF(2), + /** + * Windows Meta File + */ + PICTURE_TYPE_WMF(3), + /** + * Mac PICT format + */ + PICTURE_TYPE_PICT(4), + /** + * JPEG format + */ + PICTURE_TYPE_JPEG(5), + /** + * PNG format + */ + PICTURE_TYPE_PNG(6), + /** + * Device independent bitmap + */ + PICTURE_TYPE_DIB(7), + + ; + + int value; + + ImageType(int value) { + this.value = value; + } + } + +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/ReadCellData.java b/src/main/java/com/alibaba/excel/metadata/data/ReadCellData.java new file mode 100644 index 00000000..68231a19 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/ReadCellData.java @@ -0,0 +1,123 @@ +package com.alibaba.excel.metadata.data; + +import java.math.BigDecimal; + +import com.alibaba.excel.enums.CellDataTypeEnum; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * read cell data + * + * @author Jiaju Zhuang + */ +@Data +@NoArgsConstructor +public class ReadCellData extends CellData { + /** + * data format. + */ + private DataFormatData dataFormatData; + + public ReadCellData(CellDataTypeEnum type) { + super(); + if (type == null) { + throw new IllegalArgumentException("Type can not be null"); + } + setType(type); + } + + public ReadCellData(T data) { + super(); + setData(data); + } + + public ReadCellData(String stringValue) { + this(CellDataTypeEnum.STRING, stringValue); + } + + public ReadCellData(CellDataTypeEnum type, String stringValue) { + super(); + if (type != CellDataTypeEnum.STRING && type != CellDataTypeEnum.ERROR) { + throw new IllegalArgumentException("Only support CellDataTypeEnum.STRING and CellDataTypeEnum.ERROR"); + } + if (stringValue == null) { + throw new IllegalArgumentException("StringValue can not be null"); + } + setType(type); + setStringValue(stringValue); + } + + public ReadCellData(BigDecimal numberValue) { + super(); + if (numberValue == null) { + throw new IllegalArgumentException("DoubleValue can not be null"); + } + setType(CellDataTypeEnum.NUMBER); + setNumberValue(numberValue); + } + + public ReadCellData(Boolean booleanValue) { + super(); + if (booleanValue == null) { + throw new IllegalArgumentException("BooleanValue can not be null"); + } + setType(CellDataTypeEnum.BOOLEAN); + setBooleanValue(booleanValue); + } + + public static ReadCellData newEmptyInstance() { + return newEmptyInstance(null, null); + } + + public static ReadCellData newEmptyInstance(Integer rowIndex, Integer columnIndex) { + ReadCellData cellData = new ReadCellData<>(CellDataTypeEnum.EMPTY); + cellData.setRowIndex(rowIndex); + cellData.setColumnIndex(columnIndex); + return cellData; + } + + public static ReadCellData newInstance(Boolean booleanValue) { + return newInstance(booleanValue, null, null); + } + + public static ReadCellData newInstance(Boolean booleanValue, Integer rowIndex, Integer columnIndex) { + ReadCellData cellData = new ReadCellData<>(booleanValue); + cellData.setRowIndex(rowIndex); + cellData.setColumnIndex(columnIndex); + return cellData; + } + + public static ReadCellData newInstance(String stringValue, Integer rowIndex, Integer columnIndex) { + ReadCellData cellData = new ReadCellData<>(stringValue); + cellData.setRowIndex(rowIndex); + cellData.setColumnIndex(columnIndex); + return cellData; + } + + public static ReadCellData newInstance(BigDecimal numberValue, Integer rowIndex, Integer columnIndex) { + ReadCellData cellData = new ReadCellData<>(numberValue); + cellData.setRowIndex(rowIndex); + cellData.setColumnIndex(columnIndex); + return cellData; + } + + @Override + public ReadCellData clone() { + ReadCellData readCellData = new ReadCellData<>(); + readCellData.setType(getType()); + readCellData.setNumberValue(getNumberValue()); + readCellData.setStringValue(getStringValue()); + readCellData.setBooleanValue(getBooleanValue()); + readCellData.setData(getData()); + if (getDataFormatData() != null) { + readCellData.setDataFormatData(getDataFormatData().clone()); + } + if (getFormulaData() != null) { + readCellData.setFormulaData(getFormulaData().clone()); + } + return readCellData; + } + +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/RichTextStringData.java b/src/main/java/com/alibaba/excel/metadata/data/RichTextStringData.java new file mode 100644 index 00000000..1717741a --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/RichTextStringData.java @@ -0,0 +1,59 @@ +package com.alibaba.excel.metadata.data; + +import java.util.List; + +import com.alibaba.excel.util.ListUtils; +import com.alibaba.excel.write.metadata.style.WriteFont; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * rich text string + * + * @author Jiaju Zhuang + */ +@Data +@NoArgsConstructor +public class RichTextStringData { + private String textString; + private WriteFont writeFont; + private List intervalFontList; + + public RichTextStringData(String textString) { + this.textString = textString; + } + + @Data + @AllArgsConstructor + public static class IntervalFont { + private Integer startIndex; + private Integer endIndex; + private WriteFont writeFont; + } + + /** + * Applies a font to the specified characters of a string. + * + * @param startIndex The start index to apply the font to (inclusive) + * @param endIndex The end index to apply to font to (exclusive) + * @param writeFont The font to use. + */ + public void applyFont(int startIndex, int endIndex, WriteFont writeFont) { + if (intervalFontList == null) { + intervalFontList = ListUtils.newArrayList(); + } + intervalFontList.add(new IntervalFont(startIndex, endIndex, writeFont)); + } + + /** + * Sets the font of the entire string. + * + * @param writeFont The font to use. + */ + public void applyFont(WriteFont writeFont) { + this.writeFont = writeFont; + } + +} diff --git a/src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java b/src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java new file mode 100644 index 00000000..ed522b81 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/data/WriteCellData.java @@ -0,0 +1,119 @@ +package com.alibaba.excel.metadata.data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; +import java.util.List; + +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * wirte cell data + * + * @author Jiaju Zhuang + */ +@Data +@NoArgsConstructor +public class WriteCellData extends CellData { + /** + * Support only when writing.{@link CellDataTypeEnum#DATE} + */ + private LocalDateTime dateValue; + + /** + * rich text.{@link CellDataTypeEnum#RICH_TEXT_STRING} + */ + private RichTextStringData richTextStringDataValue; + /** + * image + */ + private List imageDataList; + /** + * comment + */ + private CommentData commentData; + /** + * hyper link + */ + private HyperlinkData hyperlinkData; + /** + * style + */ + private WriteCellStyle writeCellStyle; + + public WriteCellData(String stringValue) { + this(CellDataTypeEnum.STRING, stringValue); + } + + public WriteCellData(CellDataTypeEnum type) { + super(); + setType(type); + } + + public WriteCellData(CellDataTypeEnum type, String stringValue) { + super(); + if (type != CellDataTypeEnum.STRING && type != CellDataTypeEnum.ERROR) { + throw new IllegalArgumentException("Only support CellDataTypeEnum.STRING and CellDataTypeEnum.ERROR"); + } + if (stringValue == null) { + throw new IllegalArgumentException("StringValue can not be null"); + } + setType(type); + setStringValue(stringValue); + } + + public WriteCellData(BigDecimal numberValue) { + super(); + if (numberValue == null) { + throw new IllegalArgumentException("DoubleValue can not be null"); + } + setType(CellDataTypeEnum.NUMBER); + setNumberValue(numberValue); + } + + public WriteCellData(Boolean booleanValue) { + super(); + if (booleanValue == null) { + throw new IllegalArgumentException("BooleanValue can not be null"); + } + setType(CellDataTypeEnum.BOOLEAN); + setBooleanValue(booleanValue); + } + + public WriteCellData(Date dateValue) { + super(); + if (dateValue == null) { + throw new IllegalArgumentException("DateValue can not be null"); + } + setType(CellDataTypeEnum.DATE); + this.dateValue = LocalDateTime.ofInstant(dateValue.toInstant(), ZoneId.systemDefault()); + } + + public WriteCellData(LocalDateTime dateValue) { + super(); + if (dateValue == null) { + throw new IllegalArgumentException("DateValue can not be null"); + } + setType(CellDataTypeEnum.DATE); + this.dateValue = dateValue; + } + + public WriteCellData(byte[] image) { + super(); + if (image == null) { + throw new IllegalArgumentException("Image can not be null"); + } + setType(CellDataTypeEnum.EMPTY); + this.imageDataList = ListUtils.newArrayList(); + ImageData imageData = new ImageData(); + imageData.setImage(image); + imageDataList.add(imageData); + } + +} diff --git a/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java b/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java index 2c955ed1..bf76404f 100644 --- a/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java +++ b/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java @@ -34,6 +34,8 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.alibaba.excel.util.DateUtils; + import org.apache.poi.ss.format.CellFormat; import org.apache.poi.ss.format.CellFormatResult; import org.apache.poi.ss.usermodel.DateUtil; @@ -42,9 +44,6 @@ import org.apache.poi.ss.usermodel.FractionFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.util.DateUtils; - /** * Written with reference to {@link org.apache.poi.ss.usermodel.DataFormatter}.Made some optimizations for date * conversion. @@ -54,21 +53,31 @@ import com.alibaba.excel.util.DateUtils; * @author Jiaju Zhuang */ public class DataFormatter { - /** For logging any problems we find */ + /** + * For logging any problems we find + */ private static final Logger LOGGER = LoggerFactory.getLogger(DataFormatter.class); private static final String defaultFractionWholePartFormat = "#"; private static final String defaultFractionFractionPartFormat = "#/##"; - /** Pattern to find a number format: "0" or "#" */ + /** + * Pattern to find a number format: "0" or "#" + */ private static final Pattern numPattern = Pattern.compile("[0#]+"); - /** Pattern to find days of week as text "ddd...." */ + /** + * Pattern to find days of week as text "ddd...." + */ private static final Pattern daysAsText = Pattern.compile("([d]{3,})", Pattern.CASE_INSENSITIVE); - /** Pattern to find "AM/PM" marker */ + /** + * Pattern to find "AM/PM" marker + */ private static final Pattern amPmPattern = Pattern.compile("(([AP])[M/P]*)|(([上下])[午/下]*)", Pattern.CASE_INSENSITIVE); - /** Pattern to find formats with condition ranges e.g. [>=100] */ + /** + * Pattern to find formats with condition ranges e.g. [>=100] + */ private static final Pattern rangeConditionalPattern = Pattern.compile(".*\\[\\s*(>|>=|<|<=|=)\\s*[0-9]*\\.*[0-9].*"); @@ -107,10 +116,10 @@ public class DataFormatter { * ("#"). */ private static final String invalidDateTimeString; + static { StringBuilder buf = new StringBuilder(); - for (int i = 0; i < 255; i++) - buf.append('#'); + for (int i = 0; i < 255; i++) {buf.append('#');} invalidDateTimeString = buf.toString(); } @@ -123,14 +132,18 @@ public class DataFormatter { * The date symbols of the locale used for formatting values. */ private DateFormatSymbols dateSymbols; - /** A default format to use when a number pattern cannot be parsed. */ + /** + * A default format to use when a number pattern cannot be parsed. + */ private Format defaultNumFormat; /** * A map to cache formats. Map formats */ private final Map formats = new HashMap(); - /** stores the locale valid it the last formatting call */ + /** + * stores the locale valid it the last formatting call + */ private Locale locale; /** * true if date uses 1904 windowing, or false if using 1900 date windowing. @@ -149,28 +162,31 @@ public class DataFormatter { /** * Creates a formatter using the given locale. - * */ - public DataFormatter(GlobalConfiguration globalConfiguration) { - if (globalConfiguration == null) { + public DataFormatter(Boolean use1904windowing, Locale locale, Boolean useScientificFormat) { + if (use1904windowing == null) { this.use1904windowing = Boolean.FALSE; + } else { + this.use1904windowing = use1904windowing; + } + + if (locale == null) { this.locale = Locale.getDefault(); + } else { + this.locale = locale; + } + + if (use1904windowing == null) { this.useScientificFormat = Boolean.FALSE; } else { - this.use1904windowing = - globalConfiguration.getUse1904windowing() != null ? globalConfiguration.getUse1904windowing() - : Boolean.FALSE; - this.locale = - globalConfiguration.getLocale() != null ? globalConfiguration.getLocale() : Locale.getDefault(); - this.useScientificFormat = - globalConfiguration.getUseScientificFormat() != null ? globalConfiguration.getUseScientificFormat() - : Boolean.FALSE; + this.useScientificFormat = useScientificFormat; } + this.dateSymbols = DateFormatSymbols.getInstance(this.locale); this.decimalSymbols = DecimalFormatSymbols.getInstance(this.locale); } - private Format getFormat(Double data,Integer dataFormat, String dataFormatString) { + private Format getFormat(Double data, Short dataFormat, String dataFormatString) { // Might be better to separate out the n p and z formats, falling back to p when n and z are not set. // That however would require other code to be re factored. @@ -188,7 +204,7 @@ public class DataFormatter { if (formatStr.contains(";") && (formatStr.indexOf(';') != formatStr.lastIndexOf(';') || rangeConditionalPattern.matcher(formatStr).matches() - ) ) { + )) { try { // Ask CellFormat to get a formatter for it CellFormat cfmt = CellFormat.getInstance(locale, formatStr); @@ -200,9 +216,9 @@ public class DataFormatter { cellValueO = DateUtil.getJavaDate(data, use1904windowing); } // Wrap and return (non-cachable - CellFormat does that) - return new CellFormatResultWrapper( cfmt.apply(cellValueO) ); + return new CellFormatResultWrapper(cfmt.apply(cellValueO)); } catch (Exception e) { - LOGGER.warn("Formatting failed for format {}, falling back",formatStr, e); + LOGGER.warn("Formatting failed for format {}, falling back", formatStr, e); } } @@ -225,7 +241,7 @@ public class DataFormatter { return format; } - private Format createFormat(Integer dataFormat, String dataFormatString) { + private Format createFormat(Short dataFormat, String dataFormatString) { String formatStr = dataFormatString; Format format = checkSpecialConverter(formatStr); @@ -240,11 +256,9 @@ public class DataFormatter { // Paranoid replacement... int at = formatStr.indexOf(colour); - if (at == -1) - break; + if (at == -1) {break;} String nFormatStr = formatStr.substring(0, at) + formatStr.substring(at + colour.length()); - if (nFormatStr.equals(formatStr)) - break; + if (nFormatStr.equals(formatStr)) {break;} // Try again in case there's multiple formatStr = nFormatStr; @@ -601,13 +615,12 @@ public class DataFormatter { * number format, or no rules apply, the cell's style format is used. If the style does not have a format, the * default date format is applied. * - * @param data - * to format + * @param data to format * @param dataFormat * @param dataFormatString * @return Formatted value */ - private String getFormattedDateString(Double data, Integer dataFormat, String dataFormatString) { + private String getFormattedDateString(Double data, Short dataFormat, String dataFormatString) { Format dateFormat = getFormat(data, dataFormat, dataFormatString); if (dateFormat instanceof ExcelStyleDateFormatter) { // Hint about the raw excel value @@ -624,13 +637,12 @@ public class DataFormatter { * Format comes from either the highest priority conditional format rule with a specified format, or from the cell * style. * - * @param data - * to format + * @param data to format * @param dataFormat * @param dataFormatString * @return a formatted number string */ - private String getFormattedNumberString(BigDecimal data, Integer dataFormat, String dataFormatString) { + private String getFormattedNumberString(BigDecimal data, Short dataFormat, String dataFormatString) { Format numberFormat = getFormat(data.doubleValue(), dataFormat, dataFormatString); String formatted = numberFormat.format(data); return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation @@ -644,7 +656,7 @@ public class DataFormatter { * @param dataFormatString * @return */ - public String format(BigDecimal data, Integer dataFormat, String dataFormatString) { + public String format(BigDecimal data, Short dataFormat, String dataFormatString) { if (DateUtils.isADateFormat(dataFormat, dataFormatString)) { return getFormattedDateString(data.doubleValue(), dataFormat, dataFormatString); } @@ -663,8 +675,7 @@ public class DataFormatter { * Number value. *

* - * @param format - * A Format instance to be used as a default + * @param format A Format instance to be used as a default * @see Format#format */ public void setDefaultNumberFormat(Format format) { @@ -684,10 +695,8 @@ public class DataFormatter { * Number value. *

* - * @param excelFormatStr - * The data format string - * @param format - * A Format instance + * @param excelFormatStr The data format string + * @param format A Format instance */ public void addFormat(String excelFormatStr, Format format) { formats.put(excelFormatStr, format); @@ -715,10 +724,8 @@ public class DataFormatter { /** * Enables custom rounding mode on the given Decimal Format. * - * @param format - * DecimalFormat - * @param roundingMode - * RoundingMode + * @param format DecimalFormat + * @param roundingMode RoundingMode */ public static void setExcelStyleRoundingMode(DecimalFormat format, RoundingMode roundingMode) { format.setRoundingMode(roundingMode); @@ -737,7 +744,9 @@ public class DataFormatter { // enforce singleton } - /** Format a number as an SSN */ + /** + * Format a number as an SSN + */ public static String format(Number num) { String result = df.format(num); return result.substring(0, 3) + '-' + result.substring(3, 5) + '-' + result.substring(5, 9); @@ -767,7 +776,9 @@ public class DataFormatter { // enforce singleton } - /** Format a number as Zip + 4 */ + /** + * Format a number as Zip + 4 + */ public static String format(Number num) { String result = df.format(num); return result.substring(0, 5) + '-' + result.substring(5, 9); @@ -797,7 +808,9 @@ public class DataFormatter { // enforce singleton } - /** Format a number as a phone number */ + /** + * Format a number as a phone number + */ public static String format(Number num) { String result = df.format(num); StringBuilder sb = new StringBuilder(); @@ -833,7 +846,8 @@ public class DataFormatter { } /** - * Workaround until we merge {@link org.apache.poi.ss.usermodel.DataFormatter} with {@link CellFormat}. Constant, non-cachable wrapper around a + * Workaround until we merge {@link org.apache.poi.ss.usermodel.DataFormatter} with {@link CellFormat}. Constant, + * non-cachable wrapper around a * {@link CellFormatResult} */ private final class CellFormatResultWrapper extends Format { diff --git a/src/main/java/com/alibaba/excel/metadata/property/ExcelContentProperty.java b/src/main/java/com/alibaba/excel/metadata/property/ExcelContentProperty.java index fcad87b3..f6f92532 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/ExcelContentProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/ExcelContentProperty.java @@ -5,9 +5,12 @@ import java.lang.reflect.Field; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.metadata.Head; +import lombok.Data; + /** * @author jipengfei */ +@Data public class ExcelContentProperty { /** * Java filed @@ -20,47 +23,7 @@ public class ExcelContentProperty { /** * Custom defined converters */ - private Converter converter; + private Converter converter; private DateTimeFormatProperty dateTimeFormatProperty; private NumberFormatProperty numberFormatProperty; - - public Field getField() { - return field; - } - - public void setField(Field field) { - this.field = field; - } - - public Head getHead() { - return head; - } - - public void setHead(Head head) { - this.head = head; - } - - public DateTimeFormatProperty getDateTimeFormatProperty() { - return dateTimeFormatProperty; - } - - public void setDateTimeFormatProperty(DateTimeFormatProperty dateTimeFormatProperty) { - this.dateTimeFormatProperty = dateTimeFormatProperty; - } - - public NumberFormatProperty getNumberFormatProperty() { - return numberFormatProperty; - } - - public void setNumberFormatProperty(NumberFormatProperty numberFormatProperty) { - this.numberFormatProperty = numberFormatProperty; - } - - public Converter getConverter() { - return converter; - } - - public void setConverter(Converter converter) { - this.converter = converter; - } } diff --git a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java index a191260d..3562501d 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java @@ -3,14 +3,10 @@ package com.alibaba.excel.metadata.property; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.format.DateTimeFormat; import com.alibaba.excel.annotation.format.NumberFormat; @@ -21,15 +17,21 @@ import com.alibaba.excel.exception.ExcelCommonException; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.Holder; import com.alibaba.excel.util.ClassUtils; -import com.alibaba.excel.util.CollectionUtils; +import com.alibaba.excel.util.MapUtils; import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder; +import lombok.Data; +import org.apache.commons.collections4.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Define the header attribute of excel * * @author jipengfei */ +@Data public class ExcelHeadProperty { private static final Logger LOGGER = LoggerFactory.getLogger(ExcelHeadProperty.class); @@ -62,19 +64,19 @@ public class ExcelHeadProperty { */ private Map ignoreMap; - public ExcelHeadProperty(Holder holder, Class headClazz, List> head, Boolean convertAllFiled) { + public ExcelHeadProperty(Holder holder, Class headClazz, List> head) { this.headClazz = headClazz; - headMap = new TreeMap(); - contentPropertyMap = new TreeMap(); - fieldNameContentPropertyMap = new HashMap(); - ignoreMap = new HashMap(16); + headMap = new TreeMap<>(); + contentPropertyMap = new TreeMap<>(); + fieldNameContentPropertyMap = MapUtils.newHashMap(); + ignoreMap = MapUtils.newHashMap(); headKind = HeadKindEnum.NONE; headRowNumber = 0; if (head != null && !head.isEmpty()) { int headIndex = 0; for (int i = 0; i < head.size(); i++) { if (holder instanceof AbstractWriteHolder) { - if (((AbstractWriteHolder) holder).ignore(null, i)) { + if (((AbstractWriteHolder)holder).ignore(null, i)) { continue; } } @@ -85,7 +87,7 @@ public class ExcelHeadProperty { headKind = HeadKindEnum.STRING; } // convert headClazz to head - initColumnProperties(holder, convertAllFiled); + initColumnProperties(holder); initHeadRowNumber(); if (LOGGER.isDebugEnabled()) { @@ -113,21 +115,21 @@ public class ExcelHeadProperty { } } - private void initColumnProperties(Holder holder, Boolean convertAllFiled) { + private void initColumnProperties(Holder holder) { if (headClazz == null) { return; } // Declared fields - Map sortedAllFiledMap = new TreeMap(); - Map indexFiledMap = new TreeMap(); + Map sortedAllFiledMap = MapUtils.newTreeMap(); + Map indexFiledMap = MapUtils.newTreeMap(); boolean needIgnore = (holder instanceof AbstractWriteHolder) && ( - !CollectionUtils.isEmpty(((AbstractWriteHolder) holder).getExcludeColumnFiledNames()) || !CollectionUtils - .isEmpty(((AbstractWriteHolder) holder).getExcludeColumnIndexes()) || !CollectionUtils - .isEmpty(((AbstractWriteHolder) holder).getIncludeColumnFiledNames()) || !CollectionUtils - .isEmpty(((AbstractWriteHolder) holder).getIncludeColumnIndexes())); - ClassUtils.declaredFields(headClazz, sortedAllFiledMap, indexFiledMap, ignoreMap, convertAllFiled, needIgnore, - holder); + !CollectionUtils.isEmpty(((AbstractWriteHolder)holder).getExcludeColumnFieldNames()) || !CollectionUtils + .isEmpty(((AbstractWriteHolder)holder).getExcludeColumnIndexes()) || !CollectionUtils + .isEmpty(((AbstractWriteHolder)holder).getIncludeColumnFieldNames()) || !CollectionUtils + .isEmpty(((AbstractWriteHolder)holder).getIncludeColumnIndexes())); + + ClassUtils.declaredFields(headClazz, sortedAllFiledMap, indexFiledMap, ignoreMap, needIgnore, holder); for (Map.Entry entry : sortedAllFiledMap.entrySet()) { initOneColumnProperty(entry.getKey(), entry.getValue(), indexFiledMap.containsKey(entry.getKey())); @@ -181,63 +183,8 @@ public class ExcelHeadProperty { fieldNameContentPropertyMap.put(field.getName(), excelContentProperty); } - public Class getHeadClazz() { - return headClazz; - } - - public void setHeadClazz(Class headClazz) { - this.headClazz = headClazz; - } - - public HeadKindEnum getHeadKind() { - return headKind; - } - - public void setHeadKind(HeadKindEnum headKind) { - this.headKind = headKind; - } - public boolean hasHead() { return headKind != HeadKindEnum.NONE; } - public int getHeadRowNumber() { - return headRowNumber; - } - - public void setHeadRowNumber(int headRowNumber) { - this.headRowNumber = headRowNumber; - } - - public Map getHeadMap() { - return headMap; - } - - public void setHeadMap(Map headMap) { - this.headMap = headMap; - } - - public Map getContentPropertyMap() { - return contentPropertyMap; - } - - public void setContentPropertyMap(Map contentPropertyMap) { - this.contentPropertyMap = contentPropertyMap; - } - - public Map getFieldNameContentPropertyMap() { - return fieldNameContentPropertyMap; - } - - public void setFieldNameContentPropertyMap(Map fieldNameContentPropertyMap) { - this.fieldNameContentPropertyMap = fieldNameContentPropertyMap; - } - - public Map getIgnoreMap() { - return ignoreMap; - } - - public void setIgnoreMap(Map ignoreMap) { - this.ignoreMap = ignoreMap; - } } diff --git a/src/main/java/com/alibaba/excel/metadata/property/FontProperty.java b/src/main/java/com/alibaba/excel/metadata/property/FontProperty.java index 04caf9bb..06aec863 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/FontProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/FontProperty.java @@ -40,7 +40,7 @@ public class FontProperty { */ private Short color; /** - * Set normal,super or subscript. + * Set normal, super or subscript. * * @see Font#SS_NONE * @see Font#SS_SUPER diff --git a/src/main/java/com/alibaba/excel/metadata/property/StyleProperty.java b/src/main/java/com/alibaba/excel/metadata/property/StyleProperty.java index 9222b102..f6d0ab0b 100644 --- a/src/main/java/com/alibaba/excel/metadata/property/StyleProperty.java +++ b/src/main/java/com/alibaba/excel/metadata/property/StyleProperty.java @@ -1,5 +1,11 @@ package com.alibaba.excel.metadata.property; +import com.alibaba.excel.annotation.write.style.ContentStyle; +import com.alibaba.excel.annotation.write.style.HeadStyle; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.write.metadata.style.WriteFont; + +import lombok.Data; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.FillPatternType; @@ -8,20 +14,17 @@ import org.apache.poi.ss.usermodel.IgnoredErrorType; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.VerticalAlignment; -import com.alibaba.excel.annotation.write.style.ContentStyle; -import com.alibaba.excel.annotation.write.style.HeadStyle; -import com.alibaba.excel.write.metadata.style.WriteFont; - /** * Configuration from annotations * * @author Jiaju Zhuang */ +@Data public class StyleProperty { /** * Set the data format (must be a valid format). Built in formats are defined at {@link BuiltinFormats}. */ - private Short dataFormat; + private DataFormatData dataFormatData; /** * Set the font for this style */ @@ -48,7 +51,6 @@ public class StyleProperty { /** * Set whether the text should be wrapped. Setting this flag to true make all content visible within a * cell by displaying it on multiple lines - * */ private Boolean wrapped; /** @@ -96,7 +98,6 @@ public class StyleProperty { * Set the color to use for the right border * * @see IndexedColors - * */ private Short rightBorderColor; @@ -104,14 +105,12 @@ public class StyleProperty { * Set the color to use for the top border * * @see IndexedColors - * */ private Short topBorderColor; /** * Set the color to use for the bottom border * * @see IndexedColors - * */ private Short bottomBorderColor; /** @@ -125,7 +124,6 @@ public class StyleProperty { * Set the background fill color. * * @see IndexedColors - * */ private Short fillBackgroundColor; @@ -133,7 +131,6 @@ public class StyleProperty { * Set the foreground fill color Note: Ensure Foreground color is set prior to background color. * * @see IndexedColors - * */ private Short fillForegroundColor; /** @@ -146,7 +143,9 @@ public class StyleProperty { return null; } StyleProperty styleProperty = new StyleProperty(); - styleProperty.setDataFormat(headStyle.dataFormat()); + DataFormatData dataFormatData = new DataFormatData(); + dataFormatData.setIndex(headStyle.dataFormat()); + styleProperty.setDataFormatData(dataFormatData); styleProperty.setHidden(headStyle.hidden()); styleProperty.setLocked(headStyle.locked()); styleProperty.setQuotePrefix(headStyle.quotePrefix()); @@ -175,7 +174,9 @@ public class StyleProperty { return null; } StyleProperty styleProperty = new StyleProperty(); - styleProperty.setDataFormat(contentStyle.dataFormat()); + DataFormatData dataFormatData = new DataFormatData(); + dataFormatData.setIndex(contentStyle.dataFormat()); + styleProperty.setDataFormatData(dataFormatData); styleProperty.setHidden(contentStyle.hidden()); styleProperty.setLocked(contentStyle.locked()); styleProperty.setQuotePrefix(contentStyle.quotePrefix()); @@ -198,180 +199,4 @@ public class StyleProperty { styleProperty.setShrinkToFit(contentStyle.shrinkToFit()); return styleProperty; } - - public Short getDataFormat() { - return dataFormat; - } - - public void setDataFormat(Short dataFormat) { - this.dataFormat = dataFormat; - } - - public WriteFont getWriteFont() { - return writeFont; - } - - public void setWriteFont(WriteFont writeFont) { - this.writeFont = writeFont; - } - - public Boolean getHidden() { - return hidden; - } - - public void setHidden(Boolean hidden) { - this.hidden = hidden; - } - - public Boolean getLocked() { - return locked; - } - - public void setLocked(Boolean locked) { - this.locked = locked; - } - - public Boolean getQuotePrefix() { - return quotePrefix; - } - - public void setQuotePrefix(Boolean quotePrefix) { - this.quotePrefix = quotePrefix; - } - - public HorizontalAlignment getHorizontalAlignment() { - return horizontalAlignment; - } - - public void setHorizontalAlignment(HorizontalAlignment horizontalAlignment) { - this.horizontalAlignment = horizontalAlignment; - } - - public Boolean getWrapped() { - return wrapped; - } - - public void setWrapped(Boolean wrapped) { - this.wrapped = wrapped; - } - - public VerticalAlignment getVerticalAlignment() { - return verticalAlignment; - } - - public void setVerticalAlignment(VerticalAlignment verticalAlignment) { - this.verticalAlignment = verticalAlignment; - } - - public Short getRotation() { - return rotation; - } - - public void setRotation(Short rotation) { - this.rotation = rotation; - } - - public Short getIndent() { - return indent; - } - - public void setIndent(Short indent) { - this.indent = indent; - } - - public BorderStyle getBorderLeft() { - return borderLeft; - } - - public void setBorderLeft(BorderStyle borderLeft) { - this.borderLeft = borderLeft; - } - - public BorderStyle getBorderRight() { - return borderRight; - } - - public void setBorderRight(BorderStyle borderRight) { - this.borderRight = borderRight; - } - - public BorderStyle getBorderTop() { - return borderTop; - } - - public void setBorderTop(BorderStyle borderTop) { - this.borderTop = borderTop; - } - - public BorderStyle getBorderBottom() { - return borderBottom; - } - - public void setBorderBottom(BorderStyle borderBottom) { - this.borderBottom = borderBottom; - } - - public Short getLeftBorderColor() { - return leftBorderColor; - } - - public void setLeftBorderColor(Short leftBorderColor) { - this.leftBorderColor = leftBorderColor; - } - - public Short getRightBorderColor() { - return rightBorderColor; - } - - public void setRightBorderColor(Short rightBorderColor) { - this.rightBorderColor = rightBorderColor; - } - - public Short getTopBorderColor() { - return topBorderColor; - } - - public void setTopBorderColor(Short topBorderColor) { - this.topBorderColor = topBorderColor; - } - - public Short getBottomBorderColor() { - return bottomBorderColor; - } - - public void setBottomBorderColor(Short bottomBorderColor) { - this.bottomBorderColor = bottomBorderColor; - } - - public FillPatternType getFillPatternType() { - return fillPatternType; - } - - public void setFillPatternType(FillPatternType fillPatternType) { - this.fillPatternType = fillPatternType; - } - - public Short getFillBackgroundColor() { - return fillBackgroundColor; - } - - public void setFillBackgroundColor(Short fillBackgroundColor) { - this.fillBackgroundColor = fillBackgroundColor; - } - - public Short getFillForegroundColor() { - return fillForegroundColor; - } - - public void setFillForegroundColor(Short fillForegroundColor) { - this.fillForegroundColor = fillForegroundColor; - } - - public Boolean getShrinkToFit() { - return shrinkToFit; - } - - public void setShrinkToFit(Boolean shrinkToFit) { - this.shrinkToFit = shrinkToFit; - } } diff --git a/src/main/java/com/alibaba/excel/parameter/AnalysisParam.java b/src/main/java/com/alibaba/excel/parameter/AnalysisParam.java deleted file mode 100644 index f8679ac0..00000000 --- a/src/main/java/com/alibaba/excel/parameter/AnalysisParam.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.alibaba.excel.parameter; - -import com.alibaba.excel.support.ExcelTypeEnum; - -import java.io.InputStream; - -/** - * - * @author jipengfei - */ -@Deprecated -public class AnalysisParam { - - /** - * @see ExcelTypeEnum - */ - private ExcelTypeEnum excelTypeEnum; - - /** - * the POI filesystem that contains the Workbook stream - */ - private InputStream in; - - /** - * user defined param to listener use - */ - private Object customContent; - - public AnalysisParam(InputStream in, ExcelTypeEnum excelTypeEnum, Object customContent) { - this.in = in; - this.excelTypeEnum = excelTypeEnum; - this.customContent = customContent; - } - - public ExcelTypeEnum getExcelTypeEnum() { - return excelTypeEnum; - } - - public void setExcelTypeEnum(ExcelTypeEnum excelTypeEnum) { - this.excelTypeEnum = excelTypeEnum; - } - - public Object getCustomContent() { - return customContent; - } - - public void setCustomContent(Object customContent) { - this.customContent = customContent; - } - - public InputStream getIn() { - return in; - } - - public void setIn(InputStream in) { - this.in = in; - } -} diff --git a/src/main/java/com/alibaba/excel/parameter/GenerateParam.java b/src/main/java/com/alibaba/excel/parameter/GenerateParam.java deleted file mode 100644 index acbcfbde..00000000 --- a/src/main/java/com/alibaba/excel/parameter/GenerateParam.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.alibaba.excel.parameter; - -import java.io.OutputStream; - -import com.alibaba.excel.support.ExcelTypeEnum; - -/** - * Created by jipengfei on 17/2/19. - * - * @author jipengfei - * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter - */ -@Deprecated -public class GenerateParam { - - private OutputStream outputStream; - - private String sheetName; - - private Class clazz; - - private ExcelTypeEnum type; - - private boolean needHead = true; - - public GenerateParam(String sheetName, Class clazz, OutputStream outputStream) { - this.outputStream = outputStream; - this.sheetName = sheetName; - this.clazz = clazz; - } - - public OutputStream getOutputStream() { - return outputStream; - } - - public void setOutputStream(OutputStream outputStream) { - this.outputStream = outputStream; - } - - public String getSheetName() { - return sheetName; - } - - public void setSheetName(String sheetName) { - this.sheetName = sheetName; - } - - public Class getClazz() { - return clazz; - } - - public void setClazz(Class clazz) { - this.clazz = clazz; - } - - public ExcelTypeEnum getType() { - return type; - } - - public void setType(ExcelTypeEnum type) { - this.type = type; - } - - public boolean isNeedHead() { - return needHead; - } - - public void setNeedHead(boolean needHead) { - this.needHead = needHead; - } -} diff --git a/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java b/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java index 29d676cb..75f98065 100644 --- a/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java +++ b/src/main/java/com/alibaba/excel/read/builder/AbstractExcelReaderParameterBuilder.java @@ -1,10 +1,9 @@ package com.alibaba.excel.read.builder; -import java.util.ArrayList; - import com.alibaba.excel.metadata.AbstractParameterBuilder; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.metadata.ReadBasicParameter; +import com.alibaba.excel.util.ListUtils; /** * Build ExcelBuilder @@ -50,9 +49,9 @@ public abstract class AbstractExcelReaderParameterBuilder readListener) { if (parameter().getCustomReadListenerList() == null) { - parameter().setCustomReadListenerList(new ArrayList()); + parameter().setCustomReadListenerList(ListUtils.newArrayList()); } parameter().getCustomReadListenerList().add(readListener); return self(); diff --git a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java index 81f35862..b630eea2 100644 --- a/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java +++ b/src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java @@ -41,7 +41,7 @@ public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder - * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ public ExcelReaderBuilder file(InputStream inputStream) { readWorkbook.setInputStream(inputStream); @@ -51,7 +51,7 @@ public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder - * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ public ExcelReaderBuilder file(File file) { readWorkbook.setFile(file); @@ -61,7 +61,7 @@ public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder - * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ public ExcelReaderBuilder file(String pathName) { return file(new File(pathName)); @@ -70,7 +70,7 @@ public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder - * if false,Will transfer 'inputStream' to temporary files to improve efficiency + * if false, Will transfer 'inputStream' to temporary files to improve efficiency */ public ExcelReaderBuilder mandatoryUseInputStream(Boolean mandatoryUseInputStream) { readWorkbook.setMandatoryUseInputStream(mandatoryUseInputStream); diff --git a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java index 78b57e0a..6a814f4d 100644 --- a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java +++ b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java @@ -1,133 +1,113 @@ package com.alibaba.excel.read.listener; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.HeadKindEnum; -import com.alibaba.excel.event.AbstractIgnoreExceptionReadListener; import com.alibaba.excel.exception.ExcelDataConvertException; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; -import com.alibaba.excel.read.metadata.holder.ReadHolder; +import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; +import com.alibaba.excel.util.BeanMapUtils; import com.alibaba.excel.util.ConverterUtils; +import com.alibaba.excel.util.FieldUtils; +import com.alibaba.excel.util.MapUtils; -import net.sf.cglib.beans.BeanMap; +import org.apache.commons.collections4.CollectionUtils; /** * Convert to the object the user needs * * @author jipengfei */ -public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener> { +public class ModelBuildEventListener implements ReadListener>> { @Override - public void invokeHead(Map cellDataMap, AnalysisContext context) {} + public void invokeHead(Map> cellDataMap, AnalysisContext context) { + if (context.readSheetHolder().getMaxDataHeadSize() == null + || context.readSheetHolder().getMaxDataHeadSize() < CollectionUtils.size(cellDataMap)) { + context.readSheetHolder().setMaxDataHeadSize(CollectionUtils.size(cellDataMap)); + } + } @Override - public void invoke(Map cellDataMap, AnalysisContext context) { - ReadHolder currentReadHolder = context.currentReadHolder(); - if (HeadKindEnum.CLASS.equals(currentReadHolder.excelReadHeadProperty().getHeadKind())) { + public void invoke(Map> cellDataMap, AnalysisContext context) { + ReadSheetHolder readSheetHolder = context.readSheetHolder(); + if (HeadKindEnum.CLASS.equals(readSheetHolder.excelReadHeadProperty().getHeadKind())) { context.readRowHolder() - .setCurrentRowAnalysisResult(buildUserModel(cellDataMap, currentReadHolder, context)); + .setCurrentRowAnalysisResult(buildUserModel(cellDataMap, readSheetHolder, context)); return; } - context.readRowHolder().setCurrentRowAnalysisResult(buildStringList(cellDataMap, currentReadHolder, context)); + context.readRowHolder().setCurrentRowAnalysisResult(buildStringList(cellDataMap, readSheetHolder, context)); } - private Object buildStringList(Map cellDataMap, ReadHolder currentReadHolder, + private Object buildStringList(Map> cellDataMap, ReadSheetHolder readSheetHolder, AnalysisContext context) { int index = 0; - if (context.readWorkbookHolder().getDefaultReturnMap()) { - Map map = new LinkedHashMap(cellDataMap.size() * 4 / 3 + 1); - for (Map.Entry entry : cellDataMap.entrySet()) { - Integer key = entry.getKey(); - CellData cellData = entry.getValue(); - while (index < key) { - map.put(index, null); - index++; - } - index++; - if (cellData.getType() == CellDataTypeEnum.EMPTY) { - map.put(key, null); - continue; - } - map.put(key, - (String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(), - currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key)); - } - int headSize = currentReadHolder.excelReadHeadProperty().getHeadMap().size(); - while (index < headSize) { + Map map = MapUtils.newLinkedHashMapWithExpectedSize(cellDataMap.size()); + for (Map.Entry> entry : cellDataMap.entrySet()) { + Integer key = entry.getKey(); + ReadCellData cellData = entry.getValue(); + while (index < key) { map.put(index, null); index++; } - return map; - } else { - // Compatible with the old code the old code returns a list - List list = new ArrayList(); - for (Map.Entry entry : cellDataMap.entrySet()) { - Integer key = entry.getKey(); - CellData cellData = entry.getValue(); - while (index < key) { - list.add(null); - index++; - } - index++; - if (cellData.getType() == CellDataTypeEnum.EMPTY) { - list.add(null); - continue; - } - list.add( - (String)ConverterUtils.convertToJavaObject(cellData, null, null, currentReadHolder.converterMap(), - currentReadHolder.globalConfiguration(), context.readRowHolder().getRowIndex(), key)); - } - int headSize = currentReadHolder.excelReadHeadProperty().getHeadMap().size(); - while (index < headSize) { - list.add(null); - index++; - } - return list; + index++; + map.put(key, + (String)ConverterUtils.convertToJavaObject(cellData, null, null, readSheetHolder.converterMap(), + context, context.readRowHolder().getRowIndex(), key)); } + // fix https://github.com/alibaba/easyexcel/issues/2014 + int headSize = calculateHeadSize(readSheetHolder); + while (index < headSize) { + map.put(index, null); + index++; + } + return map; } - private Object buildUserModel(Map cellDataMap, ReadHolder currentReadHolder, + private int calculateHeadSize(ReadSheetHolder readSheetHolder) { + if (readSheetHolder.excelReadHeadProperty().getHeadMap().size() > 0) { + return readSheetHolder.excelReadHeadProperty().getHeadMap().size(); + } + if (readSheetHolder.getMaxDataHeadSize() != null) { + return readSheetHolder.getMaxDataHeadSize(); + } + return 0; + } + + private Object buildUserModel(Map> cellDataMap, ReadSheetHolder readSheetHolder, AnalysisContext context) { - ExcelReadHeadProperty excelReadHeadProperty = currentReadHolder.excelReadHeadProperty(); + ExcelReadHeadProperty excelReadHeadProperty = readSheetHolder.excelReadHeadProperty(); Object resultModel; try { resultModel = excelReadHeadProperty.getHeadClazz().newInstance(); } catch (Exception e) { throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0, - new CellData(CellDataTypeEnum.EMPTY), null, + new ReadCellData<>(CellDataTypeEnum.EMPTY), null, "Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e); } Map headMap = excelReadHeadProperty.getHeadMap(); - Map map = new HashMap(headMap.size() * 4 / 3 + 1); + Map map = MapUtils.newHashMapWithExpectedSize(headMap.size()); Map contentPropertyMap = excelReadHeadProperty.getContentPropertyMap(); for (Map.Entry entry : headMap.entrySet()) { Integer index = entry.getKey(); if (!cellDataMap.containsKey(index)) { continue; } - CellData cellData = cellDataMap.get(index); - if (cellData.getType() == CellDataTypeEnum.EMPTY) { - continue; - } + ReadCellData cellData = cellDataMap.get(index); ExcelContentProperty excelContentProperty = contentPropertyMap.get(index); Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField(), - excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration(), + excelContentProperty, readSheetHolder.converterMap(), context, context.readRowHolder().getRowIndex(), index); if (value != null) { - map.put(excelContentProperty.getField().getName(), value); + map.put(FieldUtils.resolveCglibFieldName(excelContentProperty.getField()), value); } } - BeanMap.create(resultModel).putAll(map); + BeanMapUtils.create(resultModel).putAll(map); return resultModel; } diff --git a/src/main/java/com/alibaba/excel/read/listener/PageReadListener.java b/src/main/java/com/alibaba/excel/read/listener/PageReadListener.java new file mode 100644 index 00000000..a459818d --- /dev/null +++ b/src/main/java/com/alibaba/excel/read/listener/PageReadListener.java @@ -0,0 +1,47 @@ +package com.alibaba.excel.read.listener; + +import java.util.List; +import java.util.function.Consumer; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.util.ListUtils; + +/** + * page read listener + * + * @author Jiaju Zhuang + */ +public class PageReadListener implements ReadListener { + /** + * Single handle the amount of data + */ + public static final int BATCH_COUNT = 3000; + /** + * Temporary storage of data + */ + private List cachedData = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + /** + * consumer + */ + private final Consumer> consumer; + + public PageReadListener(Consumer> consumer) { + this.consumer = consumer; + } + + @Override + public void invoke(T data, AnalysisContext context) { + cachedData.add(data); + if (cachedData.size() >= BATCH_COUNT) { + consumer.accept(cachedData); + // 存储完成清理 list + cachedData = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + consumer.accept(cachedData); + } + +} diff --git a/src/main/java/com/alibaba/excel/read/listener/ReadListener.java b/src/main/java/com/alibaba/excel/read/listener/ReadListener.java index f1d341f5..d951d1a6 100644 --- a/src/main/java/com/alibaba/excel/read/listener/ReadListener.java +++ b/src/main/java/com/alibaba/excel/read/listener/ReadListener.java @@ -4,8 +4,8 @@ import java.util.Map; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.Listener; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellExtra; +import com.alibaba.excel.metadata.data.ReadCellData; /** * Interface to listen for read results @@ -21,7 +21,7 @@ public interface ReadListener extends Listener { * @param context * @throws Exception */ - void onException(Exception exception, AnalysisContext context) throws Exception; + default void onException(Exception exception, AnalysisContext context) throws Exception {} /** * When analysis one head row trigger invoke function. @@ -29,27 +29,23 @@ public interface ReadListener extends Listener { * @param headMap * @param context */ - void invokeHead(Map headMap, AnalysisContext context); + default void invokeHead(Map> headMap, AnalysisContext context) {} /** * When analysis one row trigger invoke function. * - * @param data - * one row value. Is is same as {@link AnalysisContext#readRowHolder()} - * @param context - * analysis context + * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} + * @param context analysis context */ void invoke(T data, AnalysisContext context); /** * The current method is called when extra information is returned * - * @param extra - * extra information - * @param context - * analysis context + * @param extra extra information + * @param context analysis context */ - void extra(CellExtra extra, AnalysisContext context); + default void extra(CellExtra extra, AnalysisContext context) {} /** * if have something to do after all analysis @@ -64,5 +60,7 @@ public interface ReadListener extends Listener { * @param context * @return */ - boolean hasNext(AnalysisContext context); + default boolean hasNext(AnalysisContext context) { + return true; + } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/ReadBasicParameter.java b/src/main/java/com/alibaba/excel/read/metadata/ReadBasicParameter.java index d4035873..b5d17cbe 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/ReadBasicParameter.java +++ b/src/main/java/com/alibaba/excel/read/metadata/ReadBasicParameter.java @@ -6,11 +6,14 @@ import java.util.List; import com.alibaba.excel.metadata.BasicParameter; import com.alibaba.excel.read.listener.ReadListener; +import lombok.Data; + /** * Read basic parameter * * @author Jiaju Zhuang **/ +@Data public class ReadBasicParameter extends BasicParameter { /** * Count the number of added heads when read sheet. @@ -26,21 +29,9 @@ public class ReadBasicParameter extends BasicParameter { /** * Custom type listener run after default */ - private List customReadListenerList = new ArrayList(); - - public Integer getHeadRowNumber() { - return headRowNumber; - } - - public void setHeadRowNumber(Integer headRowNumber) { - this.headRowNumber = headRowNumber; - } - - public List getCustomReadListenerList() { - return customReadListenerList; - } + private List> customReadListenerList; - public void setCustomReadListenerList(List customReadListenerList) { - this.customReadListenerList = customReadListenerList; + public ReadBasicParameter() { + customReadListenerList = new ArrayList<>(); } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java b/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java index c9e4db93..f8106631 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java +++ b/src/main/java/com/alibaba/excel/read/metadata/ReadWorkbook.java @@ -14,11 +14,14 @@ import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.read.listener.ModelBuildEventListener; import com.alibaba.excel.support.ExcelTypeEnum; +import lombok.Data; + /** * Workbook * * @author Jiaju Zhuang **/ +@Data public class ReadWorkbook extends ReadBasicParameter { /** * Excel type @@ -27,19 +30,19 @@ public class ReadWorkbook extends ReadBasicParameter { /** * Read InputStream *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private InputStream inputStream; /** * Read file *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private File file; /** * Mandatory use 'inputStream' .Default is false. *

- * if false,Will transfer 'inputStream' to temporary files to improve efficiency + * if false, Will transfer 'inputStream' to temporary files to improve efficiency */ private Boolean mandatoryUseInputStream; /** @@ -91,141 +94,4 @@ public class ReadWorkbook extends ReadBasicParameter { * @see CellExtraTypeEnum */ private Set extraReadSet; - /** - * The default is all excel objects.Default is true. - *

- * if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a field. - *

- * if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed. - * - * @deprecated Just to be compatible with historical data, The default is always going to be convert all filed. - */ - @Deprecated - private Boolean convertAllFiled; - - /** - * List is returned by default, now map is returned by default - */ - @Deprecated - private Boolean defaultReturnMap; - - public ExcelTypeEnum getExcelType() { - return excelType; - } - - public void setExcelType(ExcelTypeEnum excelType) { - this.excelType = excelType; - } - - public InputStream getInputStream() { - return inputStream; - } - - public void setInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - - public Boolean getAutoCloseStream() { - return autoCloseStream; - } - - public void setAutoCloseStream(Boolean autoCloseStream) { - this.autoCloseStream = autoCloseStream; - } - - public Object getCustomObject() { - return customObject; - } - - public void setCustomObject(Object customObject) { - this.customObject = customObject; - } - - public Boolean getMandatoryUseInputStream() { - return mandatoryUseInputStream; - } - - public void setMandatoryUseInputStream(Boolean mandatoryUseInputStream) { - this.mandatoryUseInputStream = mandatoryUseInputStream; - } - - public ReadCache getReadCache() { - return readCache; - } - - public void setReadCache(ReadCache readCache) { - this.readCache = readCache; - } - - public Boolean getConvertAllFiled() { - return convertAllFiled; - } - - public void setConvertAllFiled(Boolean convertAllFiled) { - this.convertAllFiled = convertAllFiled; - } - - public Boolean getDefaultReturnMap() { - return defaultReturnMap; - } - - public void setDefaultReturnMap(Boolean defaultReturnMap) { - this.defaultReturnMap = defaultReturnMap; - } - - public Boolean getIgnoreEmptyRow() { - return ignoreEmptyRow; - } - - public void setIgnoreEmptyRow(Boolean ignoreEmptyRow) { - this.ignoreEmptyRow = ignoreEmptyRow; - } - - public ReadCacheSelector getReadCacheSelector() { - return readCacheSelector; - } - - public void setReadCacheSelector(ReadCacheSelector readCacheSelector) { - this.readCacheSelector = readCacheSelector; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getXlsxSAXParserFactoryName() { - return xlsxSAXParserFactoryName; - } - - public void setXlsxSAXParserFactoryName(String xlsxSAXParserFactoryName) { - this.xlsxSAXParserFactoryName = xlsxSAXParserFactoryName; - } - - public Boolean getUseDefaultListener() { - return useDefaultListener; - } - - public void setUseDefaultListener(Boolean useDefaultListener) { - this.useDefaultListener = useDefaultListener; - } - - public Set getExtraReadSet() { - return extraReadSet; - } - - public void setExtraReadSet(Set extraReadSet) { - this.extraReadSet = extraReadSet; - } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java index c431ab49..6561d377 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java @@ -1,12 +1,8 @@ package com.alibaba.excel.read.metadata.holder; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; import com.alibaba.excel.converters.DefaultConverterLoader; @@ -17,15 +13,19 @@ import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.metadata.ReadBasicParameter; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; +import com.alibaba.excel.util.ListUtils; + +import lombok.Data; +import lombok.NoArgsConstructor; /** * Read Holder * * @author Jiaju Zhuang */ +@Data +@NoArgsConstructor public abstract class AbstractReadHolder extends AbstractHolder implements ReadHolder { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractReadHolder.class); - /** * Count the number of added heads when read sheet. * @@ -44,31 +44,22 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH /** * Read listener */ - private List readListenerList; + private List> readListenerList; - public AbstractReadHolder(ReadBasicParameter readBasicParameter, AbstractReadHolder parentAbstractReadHolder, - Boolean convertAllFiled) { + public AbstractReadHolder(ReadBasicParameter readBasicParameter, AbstractReadHolder parentAbstractReadHolder) { super(readBasicParameter, parentAbstractReadHolder); - if (readBasicParameter.getUse1904windowing() == null && parentAbstractReadHolder != null) { - getGlobalConfiguration() - .setUse1904windowing(parentAbstractReadHolder.getGlobalConfiguration().getUse1904windowing()); - } else { - getGlobalConfiguration().setUse1904windowing(readBasicParameter.getUse1904windowing()); - } if (readBasicParameter.getUseScientificFormat() == null) { - if (parentAbstractReadHolder == null) { - getGlobalConfiguration().setUseScientificFormat(Boolean.FALSE); - } else { - getGlobalConfiguration() - .setUseScientificFormat(parentAbstractReadHolder.getGlobalConfiguration().getUseScientificFormat()); + if (parentAbstractReadHolder != null) { + getGlobalConfiguration().setUseScientificFormat( + parentAbstractReadHolder.getGlobalConfiguration().getUseScientificFormat()); } } else { getGlobalConfiguration().setUseScientificFormat(readBasicParameter.getUseScientificFormat()); } // Initialization property - this.excelReadHeadProperty = new ExcelReadHeadProperty(this, getClazz(), getHead(), convertAllFiled); + this.excelReadHeadProperty = new ExcelReadHeadProperty(this, getClazz(), getHead()); if (readBasicParameter.getHeadRowNumber() == null) { if (parentAbstractReadHolder == null) { if (excelReadHeadProperty.hasHead()) { @@ -84,9 +75,9 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH } if (parentAbstractReadHolder == null) { - this.readListenerList = new ArrayList(); + this.readListenerList = ListUtils.newArrayList(); } else { - this.readListenerList = new ArrayList(parentAbstractReadHolder.getReadListenerList()); + this.readListenerList = ListUtils.newArrayList(parentAbstractReadHolder.getReadListenerList()); } if (HolderEnum.WORKBOOK.equals(holderType())) { Boolean useDefaultListener = ((ReadWorkbook)readBasicParameter).getUseDefaultListener(); @@ -102,11 +93,11 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH if (parentAbstractReadHolder == null) { setConverterMap(DefaultConverterLoader.loadDefaultReadConverter()); } else { - setConverterMap(new HashMap(parentAbstractReadHolder.getConverterMap())); + setConverterMap(new HashMap<>(parentAbstractReadHolder.getConverterMap())); } if (readBasicParameter.getCustomConverterList() != null && !readBasicParameter.getCustomConverterList().isEmpty()) { - for (Converter converter : readBasicParameter.getCustomConverterList()) { + for (Converter converter : readBasicParameter.getCustomConverterList()) { getConverterMap().put( ConverterKeyBuild.buildKey(converter.supportJavaTypeKey(), converter.supportExcelTypeKey()), converter); @@ -114,32 +105,8 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH } } - public List getReadListenerList() { - return readListenerList; - } - - public void setReadListenerList(List readListenerList) { - this.readListenerList = readListenerList; - } - - public ExcelReadHeadProperty getExcelReadHeadProperty() { - return excelReadHeadProperty; - } - - public void setExcelReadHeadProperty(ExcelReadHeadProperty excelReadHeadProperty) { - this.excelReadHeadProperty = excelReadHeadProperty; - } - - public Integer getHeadRowNumber() { - return headRowNumber; - } - - public void setHeadRowNumber(Integer headRowNumber) { - this.headRowNumber = headRowNumber; - } - @Override - public List readListenerList() { + public List> readListenerList() { return getReadListenerList(); } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadHolder.java index 43e13013..32ac6ee9 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadHolder.java @@ -18,7 +18,7 @@ public interface ReadHolder extends ConfigurationHolder { * * @return Current {@link ReadListener} */ - List readListenerList(); + List> readListenerList(); /** * What {@link ExcelReadHeadProperty} does the currently operated cell need to execute diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java index 7a5272a6..558bec57 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java @@ -5,15 +5,20 @@ import java.util.Map; import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.metadata.Cell; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.CellExtra; +import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.read.metadata.ReadSheet; +import lombok.Data; +import lombok.NoArgsConstructor; + /** * sheet holder * * @author Jiaju Zhuang */ +@Data +@NoArgsConstructor public class ReadSheetHolder extends AbstractReadHolder { /** @@ -51,113 +56,37 @@ public class ReadSheetHolder extends AbstractReadHolder { /** * Current CellData */ - private CellData tempCellData; + private ReadCellData tempCellData; + /** + * Read the size of the largest head in sheet head data. + * see https://github.com/alibaba/easyexcel/issues/2014 + */ + private Integer maxDataHeadSize; public ReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { - super(readSheet, readWorkbookHolder, readWorkbookHolder.getReadWorkbook().getConvertAllFiled()); + super(readSheet, readWorkbookHolder); this.readSheet = readSheet; this.parentReadWorkbookHolder = readWorkbookHolder; this.sheetNo = readSheet.getSheetNo(); this.sheetName = readSheet.getSheetName(); - this.cellMap = new LinkedHashMap(); + this.cellMap = new LinkedHashMap<>(); this.rowIndex = -1; } - public ReadSheet getReadSheet() { - return readSheet; - } - - public void setReadSheet(ReadSheet readSheet) { - this.readSheet = readSheet; - } - - public ReadWorkbookHolder getParentReadWorkbookHolder() { - return parentReadWorkbookHolder; - } - - public void setParentReadWorkbookHolder(ReadWorkbookHolder parentReadWorkbookHolder) { - this.parentReadWorkbookHolder = parentReadWorkbookHolder; - } - - public Integer getSheetNo() { - return sheetNo; - } - - public void setSheetNo(Integer sheetNo) { - this.sheetNo = sheetNo; - } - - public String getSheetName() { - return sheetName; - } - - public void setSheetName(String sheetName) { - this.sheetName = sheetName; - } - /** - * Approximate total number of rows + * Approximate total number of rows. + * use: getApproximateTotalRowNumber() * * @return - * @see #getApproximateTotalRowNumber() */ @Deprecated public Integer getTotal() { return approximateTotalRowNumber; } - /** - * Approximate total number of rows - * - * @return - */ - public Integer getApproximateTotalRowNumber() { - return approximateTotalRowNumber; - } - - public void setApproximateTotalRowNumber(Integer approximateTotalRowNumber) { - this.approximateTotalRowNumber = approximateTotalRowNumber; - } - - public Map getCellMap() { - return cellMap; - } - - public void setCellMap(Map cellMap) { - this.cellMap = cellMap; - } - - public Integer getRowIndex() { - return rowIndex; - } - - public void setRowIndex(Integer rowIndex) { - this.rowIndex = rowIndex; - } - - public CellData getTempCellData() { - return tempCellData; - } - - public void setTempCellData(CellData tempCellData) { - this.tempCellData = tempCellData; - } - - public CellExtra getCellExtra() { - return cellExtra; - } - - public void setCellExtra(CellExtra cellExtra) { - this.cellExtra = cellExtra; - } - @Override public HolderEnum holderType() { return HolderEnum.SHEET; } - @Override - public String toString() { - return "ReadSheetHolder{" + "sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' + "} " + super.toString(); - } } diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java index 375e32cc..b1e03e4f 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java @@ -19,11 +19,16 @@ import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.support.ExcelTypeEnum; +import lombok.Data; +import lombok.NoArgsConstructor; + /** * Workbook holder * * @author Jiaju Zhuang */ +@Data +@NoArgsConstructor public class ReadWorkbookHolder extends AbstractReadHolder { /** @@ -33,19 +38,19 @@ public class ReadWorkbookHolder extends AbstractReadHolder { /** * Read InputStream *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private InputStream inputStream; /** * Read file *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private File file; /** * Mandatory use 'inputStream' .Default is false. *

- * if false,Will transfer 'inputStream' to temporary files to improve efficiency + * if false, Will transfer 'inputStream' to temporary files to improve efficiency */ private Boolean mandatoryUseInputStream; /** @@ -101,28 +106,13 @@ public class ReadWorkbookHolder extends AbstractReadHolder { */ private Boolean readAll; - /** - * The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a - * field. if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed. - * - * @deprecated Just to be compatible with historical data, The default is always going to be convert all filed. - */ - @Deprecated - private Boolean convertAllFiled; - - /** - * List is returned by default, now map is returned by default - */ - @Deprecated - private Boolean defaultReturnMap; - /** * Prevent repeating sheet */ private Set hasReadSheet; public ReadWorkbookHolder(ReadWorkbook readWorkbook) { - super(readWorkbook, null, readWorkbook.getConvertAllFiled()); + super(readWorkbook, null); this.readWorkbook = readWorkbook; if (readWorkbook.getInputStream() != null) { this.inputStream = readWorkbook.getInputStream(); @@ -157,11 +147,6 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.readCacheSelector = readWorkbook.getReadCacheSelector(); } } - if (readWorkbook.getDefaultReturnMap() == null) { - this.defaultReturnMap = Boolean.TRUE; - } else { - this.defaultReturnMap = readWorkbook.getDefaultReturnMap(); - } if (readWorkbook.getExtraReadSet() == null) { this.extraReadSet = new HashSet(); } else { @@ -171,157 +156,6 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.password = readWorkbook.getPassword(); } - public ReadWorkbook getReadWorkbook() { - return readWorkbook; - } - - public void setReadWorkbook(ReadWorkbook readWorkbook) { - this.readWorkbook = readWorkbook; - } - - public InputStream getInputStream() { - return inputStream; - } - - public void setInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - - public Boolean getAutoCloseStream() { - return autoCloseStream; - } - - public void setAutoCloseStream(Boolean autoCloseStream) { - this.autoCloseStream = autoCloseStream; - } - - public ExcelTypeEnum getExcelType() { - return excelType; - } - - public void setExcelType(ExcelTypeEnum excelType) { - this.excelType = excelType; - } - - public Object getCustomObject() { - return customObject; - } - - public void setCustomObject(Object customObject) { - this.customObject = customObject; - } - - public Boolean getIgnoreEmptyRow() { - return ignoreEmptyRow; - } - - public void setIgnoreEmptyRow(Boolean ignoreEmptyRow) { - this.ignoreEmptyRow = ignoreEmptyRow; - } - - public ReadCache getReadCache() { - return readCache; - } - - public void setReadCache(ReadCache readCache) { - this.readCache = readCache; - } - - public ReadCacheSelector getReadCacheSelector() { - return readCacheSelector; - } - - public void setReadCacheSelector(ReadCacheSelector readCacheSelector) { - this.readCacheSelector = readCacheSelector; - } - - public Boolean getMandatoryUseInputStream() { - return mandatoryUseInputStream; - } - - public void setMandatoryUseInputStream(Boolean mandatoryUseInputStream) { - this.mandatoryUseInputStream = mandatoryUseInputStream; - } - - public File getTempFile() { - return tempFile; - } - - public void setTempFile(File tempFile) { - this.tempFile = tempFile; - } - - public Boolean getConvertAllFiled() { - return convertAllFiled; - } - - public void setConvertAllFiled(Boolean convertAllFiled) { - this.convertAllFiled = convertAllFiled; - } - - public Set getHasReadSheet() { - return hasReadSheet; - } - - public void setHasReadSheet(Set hasReadSheet) { - this.hasReadSheet = hasReadSheet; - } - - public Boolean getDefaultReturnMap() { - return defaultReturnMap; - } - - public void setDefaultReturnMap(Boolean defaultReturnMap) { - this.defaultReturnMap = defaultReturnMap; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Set getExtraReadSet() { - return extraReadSet; - } - - public void setExtraReadSet(Set extraReadSet) { - this.extraReadSet = extraReadSet; - } - - public List getActualSheetDataList() { - return actualSheetDataList; - } - - public void setActualSheetDataList(List actualSheetDataList) { - this.actualSheetDataList = actualSheetDataList; - } - - public List getParameterSheetDataList() { - return parameterSheetDataList; - } - - public void setParameterSheetDataList(List parameterSheetDataList) { - this.parameterSheetDataList = parameterSheetDataList; - } - - public Boolean getReadAll() { - return readAll; - } - - public void setReadAll(Boolean readAll) { - this.readAll = readAll; - } @Override public HolderEnum holderType() { diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadSheetHolder.java new file mode 100644 index 00000000..d6bf6953 --- /dev/null +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadSheetHolder.java @@ -0,0 +1,20 @@ +package com.alibaba.excel.read.metadata.holder.csv; + +import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; + +import lombok.Data; + +/** + * sheet holder + * + * @author Jiaju Zhuang + */ +@Data +public class CsvReadSheetHolder extends ReadSheetHolder { + + public CsvReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { + super(readSheet, readWorkbookHolder); + } +} diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadWorkbookHolder.java new file mode 100644 index 00000000..8066fab6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadWorkbookHolder.java @@ -0,0 +1,25 @@ +package com.alibaba.excel.read.metadata.holder.csv; + +import com.alibaba.excel.read.metadata.ReadWorkbook; +import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; +import com.alibaba.excel.support.ExcelTypeEnum; + +import lombok.Data; +import org.apache.commons.csv.CSVFormat; + +/** + * Workbook holder + * + * @author Jiaju Zhuang + */ +@Data +public class CsvReadWorkbookHolder extends ReadWorkbookHolder { + + private CSVFormat csvFormat; + + public CsvReadWorkbookHolder(ReadWorkbook readWorkbook) { + super(readWorkbook); + setExcelType(ExcelTypeEnum.CSV); + this.csvFormat = CSVFormat.DEFAULT; + } +} diff --git a/src/main/java/com/alibaba/excel/read/metadata/property/ExcelReadHeadProperty.java b/src/main/java/com/alibaba/excel/read/metadata/property/ExcelReadHeadProperty.java index 1b7ae17c..9c332ceb 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/property/ExcelReadHeadProperty.java +++ b/src/main/java/com/alibaba/excel/read/metadata/property/ExcelReadHeadProperty.java @@ -12,7 +12,7 @@ import com.alibaba.excel.metadata.property.ExcelHeadProperty; */ public class ExcelReadHeadProperty extends ExcelHeadProperty { - public ExcelReadHeadProperty(Holder holder, Class headClazz, List> head, Boolean convertAllFiled) { - super(holder, headClazz, head, convertAllFiled); + public ExcelReadHeadProperty(Holder holder, Class headClazz, List> head) { + super(holder, headClazz, head); } } diff --git a/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java b/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java index ddd19504..c3c50234 100644 --- a/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java +++ b/src/main/java/com/alibaba/excel/read/processor/DefaultAnalysisEventProcessor.java @@ -4,16 +4,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.enums.HeadKindEnum; import com.alibaba.excel.enums.RowTypeEnum; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisStopException; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.metadata.holder.ReadRowHolder; @@ -21,6 +18,9 @@ import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; import com.alibaba.excel.util.ConverterUtils; import com.alibaba.excel.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Analysis event * @@ -82,7 +82,7 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { private void dealData(AnalysisContext analysisContext) { ReadRowHolder readRowHolder = analysisContext.readRowHolder(); - Map cellDataMap = (Map)readRowHolder.getCellMap(); + Map> cellDataMap = (Map)readRowHolder.getCellMap(); readRowHolder.setCurrentRowAnalysisResult(cellDataMap); int rowIndex = readRowHolder.getRowIndex(); int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber(); @@ -111,7 +111,7 @@ public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor { } } - private void buildHead(AnalysisContext analysisContext, Map cellDataMap) { + private void buildHead(AnalysisContext analysisContext, Map> cellDataMap) { if (!HeadKindEnum.CLASS.equals(analysisContext.currentReadHolder().excelReadHeadProperty().getHeadKind())) { return; } diff --git a/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java b/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java index cdca07fd..eb4c4cbd 100644 --- a/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java +++ b/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java @@ -5,17 +5,21 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; -import org.apache.poi.poifs.filesystem.FileMagic; - import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelCommonException; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.util.StringUtils; +import org.apache.poi.poifs.filesystem.FileMagic; + /** * @author jipengfei */ public enum ExcelTypeEnum { + /** + * csv + */ + CSV(".csv"), /** * xls */ @@ -48,11 +52,8 @@ public enum ExcelTypeEnum { } // If there is a password, use the FileMagic first if (!StringUtils.isEmpty(readWorkbook.getPassword())) { - BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file)); - try { + try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) { return recognitionExcelType(bufferedInputStream); - } finally { - bufferedInputStream.close(); } } // Use the name to determine the type @@ -61,13 +62,12 @@ public enum ExcelTypeEnum { return XLSX; } else if (fileName.endsWith(XLS.getValue())) { return XLS; + } else if (fileName.endsWith(CSV.getValue())) { + return CSV; } if (StringUtils.isEmpty(readWorkbook.getPassword())) { - BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file)); - try { + try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) { return recognitionExcelType(bufferedInputStream); - } finally { - bufferedInputStream.close(); } } } @@ -78,8 +78,6 @@ public enum ExcelTypeEnum { return recognitionExcelType(inputStream); } catch (ExcelCommonException e) { throw e; - } catch (ExcelAnalysisException e) { - throw e; } catch (Exception e) { throw new ExcelCommonException( "Convert excel format exception.You can try specifying the 'excelType' yourself", e); diff --git a/src/main/java/com/alibaba/excel/util/BeanMapUtils.java b/src/main/java/com/alibaba/excel/util/BeanMapUtils.java new file mode 100644 index 00000000..eab4a70f --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/BeanMapUtils.java @@ -0,0 +1,40 @@ +package com.alibaba.excel.util; + +import net.sf.cglib.beans.BeanMap; +import net.sf.cglib.beans.BeanMap.Generator; +import net.sf.cglib.core.DefaultNamingPolicy; + +/** + * bean utils + * + * @author Jiaju Zhuang + */ +public class BeanMapUtils { + + /** + * Helper method to create a new BeanMap. For finer + * control over the generated instance, use a new instance of + * BeanMap.Generator instead of this static method. + * + * Custom naming policy to prevent null pointer exceptions. + * see: https://github.com/alibaba/easyexcel/issues/2064 + * + * @param bean the JavaBean underlying the map + * @return a new BeanMap instance + */ + public static BeanMap create(Object bean) { + Generator gen = new Generator(); + gen.setBean(bean); + gen.setNamingPolicy(EasyExcelNamingPolicy.INSTANCE); + return gen.create(); + } + + public static class EasyExcelNamingPolicy extends DefaultNamingPolicy { + public static final EasyExcelNamingPolicy INSTANCE = new EasyExcelNamingPolicy(); + + @Override + protected String getTag() { + return "ByEasyExcelCGLIB"; + } + } +} diff --git a/src/main/java/com/alibaba/excel/util/BooleanUtils.java b/src/main/java/com/alibaba/excel/util/BooleanUtils.java index 55c48a18..18f6dd39 100644 --- a/src/main/java/com/alibaba/excel/util/BooleanUtils.java +++ b/src/main/java/com/alibaba/excel/util/BooleanUtils.java @@ -25,4 +25,79 @@ public class BooleanUtils { } } + + // boolean Boolean methods + //----------------------------------------------------------------------- + /** + *

Checks if a {@code Boolean} value is {@code true}, + * handling {@code null} by returning {@code false}.

+ * + *
+     *   BooleanUtils.isTrue(Boolean.TRUE)  = true
+     *   BooleanUtils.isTrue(Boolean.FALSE) = false
+     *   BooleanUtils.isTrue(null)          = false
+     * 
+ * + * @param bool the boolean to check, null returns {@code false} + * @return {@code true} only if the input is non-null and true + * @since 2.1 + */ + public static boolean isTrue(final Boolean bool) { + return Boolean.TRUE.equals(bool); + } + + /** + *

Checks if a {@code Boolean} value is not {@code true}, + * handling {@code null} by returning {@code true}.

+ * + *
+     *   BooleanUtils.isNotTrue(Boolean.TRUE)  = false
+     *   BooleanUtils.isNotTrue(Boolean.FALSE) = true
+     *   BooleanUtils.isNotTrue(null)          = true
+     * 
+ * + * @param bool the boolean to check, null returns {@code true} + * @return {@code true} if the input is null or false + * @since 2.3 + */ + public static boolean isNotTrue(final Boolean bool) { + return !isTrue(bool); + } + + /** + *

Checks if a {@code Boolean} value is {@code false}, + * handling {@code null} by returning {@code false}.

+ * + *
+     *   BooleanUtils.isFalse(Boolean.TRUE)  = false
+     *   BooleanUtils.isFalse(Boolean.FALSE) = true
+     *   BooleanUtils.isFalse(null)          = false
+     * 
+ * + * @param bool the boolean to check, null returns {@code false} + * @return {@code true} only if the input is non-null and false + * @since 2.1 + */ + public static boolean isFalse(final Boolean bool) { + return Boolean.FALSE.equals(bool); + } + + /** + *

Checks if a {@code Boolean} value is not {@code false}, + * handling {@code null} by returning {@code true}.

+ * + *
+     *   BooleanUtils.isNotFalse(Boolean.TRUE)  = true
+     *   BooleanUtils.isNotFalse(Boolean.FALSE) = false
+     *   BooleanUtils.isNotFalse(null)          = true
+     * 
+ * + * @param bool the boolean to check, null returns {@code true} + * @return {@code true} if the input is null or true + * @since 2.3 + */ + public static boolean isNotFalse(final Boolean bool) { + return !isFalse(bool); + } + } diff --git a/src/main/java/com/alibaba/excel/util/ClassUtils.java b/src/main/java/com/alibaba/excel/util/ClassUtils.java index 936c325d..50e9351a 100644 --- a/src/main/java/com/alibaba/excel/util/ClassUtils.java +++ b/src/main/java/com/alibaba/excel/util/ClassUtils.java @@ -6,6 +6,8 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -14,11 +16,8 @@ import java.util.concurrent.ConcurrentHashMap; import com.alibaba.excel.annotation.ExcelIgnore; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; -import com.alibaba.excel.event.Handler; import com.alibaba.excel.exception.ExcelCommonException; -import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.Holder; -import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.metadata.holder.WriteHolder; /** @@ -28,54 +27,72 @@ import com.alibaba.excel.write.metadata.holder.WriteHolder; **/ public class ClassUtils { - private static final Map> FIELD_CACHE = - new ConcurrentHashMap>(); + public static final Map, SoftReference> FIELD_CACHE = new ConcurrentHashMap<>(); - public static void declaredFields(Class clazz, Map sortedAllFiledMap, - Map indexFiledMap, Map ignoreMap, Boolean convertAllFiled, - Boolean needIgnore, Holder holder) { - FieldCache fieldCache = getFieldCache(clazz, convertAllFiled); + /** + * Parsing filed in the class + * + * @param clazz Need to parse the class + * @param sortedAllFiledMap Complete the map of sorts + * @param indexFiledMap Use the index to sort fields + * @param ignoreMap You want to ignore field map + * @param needIgnore If you want to ignore fields need to ignore + * @param holder holder + */ + public static void declaredFields(Class clazz, Map sortedAllFiledMap, + Map indexFiledMap, Map ignoreMap, Boolean needIgnore, Holder holder) { + FieldCache fieldCache = getFieldCache(clazz); if (fieldCache == null) { return; } if (ignoreMap != null) { ignoreMap.putAll(fieldCache.getIgnoreMap()); } - Map tempIndexFildMap = indexFiledMap; - if (tempIndexFildMap == null) { - tempIndexFildMap = new TreeMap(); + Map tempIndexFieldMap = indexFiledMap; + if (tempIndexFieldMap == null) { + tempIndexFieldMap = MapUtils.newTreeMap(); } - tempIndexFildMap.putAll(fieldCache.getIndexFiledMap()); + tempIndexFieldMap.putAll(fieldCache.getIndexFiledMap()); + Map originSortedAllFiledMap = fieldCache.getSortedAllFiledMap(); if (!needIgnore) { - sortedAllFiledMap.putAll(fieldCache.getSortedAllFiledMap()); + sortedAllFiledMap.putAll(originSortedAllFiledMap); return; } int index = 0; - for (Map.Entry entry : fieldCache.getSortedAllFiledMap().entrySet()) { + for (Map.Entry entry : originSortedAllFiledMap.entrySet()) { + Integer key = entry.getKey(); Field field = entry.getValue(); - if (((WriteHolder) holder).ignore(entry.getValue().getName(), entry.getKey())) { + + // The current field needs to be ignored + if (((WriteHolder)holder).ignore(entry.getValue().getName(), entry.getKey())) { if (ignoreMap != null) { ignoreMap.put(field.getName(), field); } - while (tempIndexFildMap.containsKey(index)) { - tempIndexFildMap.remove(index); - index++; - } + tempIndexFieldMap.remove(index); } else { - sortedAllFiledMap.put(index, field); - index++; + // Mandatory sorted fields + if (tempIndexFieldMap.containsKey(key)) { + sortedAllFiledMap.put(key, field); + } else { + // Need to reorder automatically + // Check whether the current key is already in use + while (sortedAllFiledMap.containsKey(index)) { + index++; + } + sortedAllFiledMap.put(index++, field); + } } } } - public static void declaredFields(Class clazz, Map sortedAllFiledMap, Boolean convertAllFiled, - Boolean needIgnore, WriteHolder writeHolder) { - declaredFields(clazz, sortedAllFiledMap, null, null, convertAllFiled, needIgnore, writeHolder); + public static void declaredFields(Class clazz, Map sortedAllFiledMap, Boolean needIgnore, + WriteHolder writeHolder) { + declaredFields(clazz, sortedAllFiledMap, null, null, needIgnore, writeHolder); } - private static FieldCache getFieldCache(Class clazz, Boolean convertAllFiled) { + private static FieldCache getFieldCache(Class clazz) { if (clazz == null) { return null; } @@ -88,17 +105,17 @@ public class ClassUtils { if (fieldCacheSoftReference != null && fieldCacheSoftReference.get() != null) { return fieldCacheSoftReference.get(); } - declaredFields(clazz, convertAllFiled); + declaredFields(clazz); } return FIELD_CACHE.get(clazz).get(); } - private static void declaredFields(Class clazz, Boolean convertAllFiled) { - List tempFieldList = new ArrayList(); - Class tempClass = clazz; + private static void declaredFields(Class clazz) { + List tempFieldList = new ArrayList<>(); + Class tempClass = clazz; // When the parent class is null, it indicates that the parent class (Object class) has reached the top // level. - while (tempClass != null && tempClass != BaseRowModel.class) { + while (tempClass != null) { Collections.addAll(tempFieldList, tempClass.getDeclaredFields()); // Get the parent class and give it to yourself tempClass = tempClass.getSuperclass(); @@ -108,10 +125,9 @@ public class ClassUtils { Map indexFiledMap = new TreeMap(); Map ignoreMap = new HashMap(16); - ExcelIgnoreUnannotated excelIgnoreUnannotated = - (ExcelIgnoreUnannotated) clazz.getAnnotation(ExcelIgnoreUnannotated.class); + ExcelIgnoreUnannotated excelIgnoreUnannotated = clazz.getAnnotation(ExcelIgnoreUnannotated.class); for (Field field : tempFieldList) { - declaredOneField(field, orderFiledMap, indexFiledMap, ignoreMap, excelIgnoreUnannotated, convertAllFiled); + declaredOneField(field, orderFiledMap, indexFiledMap, ignoreMap, excelIgnoreUnannotated); } FIELD_CACHE.put(clazz, new SoftReference( new FieldCache(buildSortedAllFiledMap(orderFiledMap, indexFiledMap), indexFiledMap, ignoreMap))); @@ -141,16 +157,16 @@ public class ClassUtils { } private static void declaredOneField(Field field, Map> orderFiledMap, - Map indexFiledMap, Map ignoreMap, ExcelIgnoreUnannotated excelIgnoreUnannotated, - Boolean convertAllFiled) { + Map indexFiledMap, Map ignoreMap, + ExcelIgnoreUnannotated excelIgnoreUnannotated) { + ExcelIgnore excelIgnore = field.getAnnotation(ExcelIgnore.class); if (excelIgnore != null) { ignoreMap.put(field.getName(), field); return; } ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); - boolean noExcelProperty = excelProperty == null - && ((convertAllFiled != null && !convertAllFiled) || excelIgnoreUnannotated != null); + boolean noExcelProperty = excelProperty == null && excelIgnoreUnannotated != null; if (noExcelProperty) { ignoreMap.put(field.getName(), field); return; @@ -175,19 +191,15 @@ public class ClassUtils { if (excelProperty != null) { order = excelProperty.order(); } - List orderFiledList = orderFiledMap.get(order); - if (orderFiledList == null) { - orderFiledList = new ArrayList(); - orderFiledMap.put(order, orderFiledList); - } + List orderFiledList = orderFiledMap.computeIfAbsent(order, key -> ListUtils.newArrayList()); orderFiledList.add(field); } private static class FieldCache { - private Map sortedAllFiledMap; - private Map indexFiledMap; - private Map ignoreMap; + private final Map sortedAllFiledMap; + private final Map indexFiledMap; + private final Map ignoreMap; public FieldCache(Map sortedAllFiledMap, Map indexFiledMap, Map ignoreMap) { @@ -208,4 +220,49 @@ public class ClassUtils { return ignoreMap; } } + + /** + *

Gets a {@code List} of all interfaces implemented by the given + * class and its superclasses.

+ * + *

The order is determined by looking through each interface in turn as + * declared in the source file and following its hierarchy up. Then each + * superclass is considered in the same way. Later duplicates are ignored, + * so the order is maintained.

+ * + * @param cls the class to look up, may be {@code null} + * @return the {@code List} of interfaces in order, + * {@code null} if null input + */ + public static List> getAllInterfaces(final Class cls) { + if (cls == null) { + return null; + } + + final LinkedHashSet> interfacesFound = new LinkedHashSet<>(); + getAllInterfaces(cls, interfacesFound); + + return new ArrayList<>(interfacesFound); + } + + /** + * Gets the interfaces for the specified class. + * + * @param cls the class to look up, may be {@code null} + * @param interfacesFound the {@code Set} of interfaces for the class + */ + private static void getAllInterfaces(Class cls, final HashSet> interfacesFound) { + while (cls != null) { + final Class[] interfaces = cls.getInterfaces(); + + for (final Class i : interfaces) { + if (interfacesFound.add(i)) { + getAllInterfaces(i, interfacesFound); + } + } + + cls = cls.getSuperclass(); + } + } + } diff --git a/src/main/java/com/alibaba/excel/util/CollectionUtils.java b/src/main/java/com/alibaba/excel/util/CollectionUtils.java deleted file mode 100644 index f413be17..00000000 --- a/src/main/java/com/alibaba/excel/util/CollectionUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.alibaba.excel.util; - -import java.util.Collection; -import java.util.Map; - -/** - * Collection utils - * - * @author jipengfei - */ -public class CollectionUtils { - - private CollectionUtils() {} - - public static boolean isEmpty(Collection collection) { - return (collection == null || collection.isEmpty()); - } - - public static boolean isEmpty(Map map) { - return (map == null || map.isEmpty()); - } -} diff --git a/src/main/java/com/alibaba/excel/util/ConverterUtils.java b/src/main/java/com/alibaba/excel/util/ConverterUtils.java index 43b12c53..b666be6e 100644 --- a/src/main/java/com/alibaba/excel/util/ConverterUtils.java +++ b/src/main/java/com/alibaba/excel/util/ConverterUtils.java @@ -3,18 +3,18 @@ package com.alibaba.excel.util; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.HashMap; import java.util.Map; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; +import com.alibaba.excel.converters.NullableObjectConverter; +import com.alibaba.excel.converters.ReadConverterContext; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.exception.ExcelDataConvertException; -import com.alibaba.excel.metadata.CellData; -import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; -import com.alibaba.excel.read.metadata.holder.ReadHolder; +import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; /** * Converting objects @@ -22,6 +22,7 @@ import com.alibaba.excel.read.metadata.holder.ReadHolder; * @author Jiaju Zhuang **/ public class ConverterUtils { + public static Class defaultClassGeneric = String.class; private ConverterUtils() {} @@ -32,13 +33,14 @@ public class ConverterUtils { * @param context * @return */ - public static Map convertToStringMap(Map cellDataMap, AnalysisContext context) { - Map stringMap = new HashMap(cellDataMap.size() * 4 / 3 + 1); - ReadHolder currentReadHolder = context.currentReadHolder(); + public static Map convertToStringMap(Map> cellDataMap, + AnalysisContext context) { + Map stringMap = MapUtils.newHashMapWithExpectedSize(cellDataMap.size()); + ReadSheetHolder readSheetHolder = context.readSheetHolder(); int index = 0; - for (Map.Entry entry : cellDataMap.entrySet()) { + for (Map.Entry> entry : cellDataMap.entrySet()) { Integer key = entry.getKey(); - CellData cellData = entry.getValue(); + ReadCellData cellData = entry.getValue(); while (index < key) { stringMap.put(index, null); index++; @@ -48,15 +50,15 @@ public class ConverterUtils { stringMap.put(key, null); continue; } - Converter converter = - currentReadHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType())); + Converter converter = + readSheetHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType())); if (converter == null) { throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null, "Converter not found, convert " + cellData.getType() + " to String"); } try { stringMap.put(key, - (String)(converter.convertToJavaData(cellData, null, currentReadHolder.globalConfiguration()))); + (String)(converter.convertToJavaData(new ReadConverterContext<>(cellData, null, context)))); } catch (Exception e) { throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), key, cellData, null, "Convert data " + cellData + " to String error ", e); @@ -72,56 +74,71 @@ public class ConverterUtils { * @param field * @param contentProperty * @param converterMap - * @param globalConfiguration + * @param context * @param rowIndex * @param columnIndex * @return */ - public static Object convertToJavaObject(CellData cellData, Field field, ExcelContentProperty contentProperty, - Map converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex, - Integer columnIndex) { - Class clazz; + public static Object convertToJavaObject(ReadCellData cellData, Field field, + ExcelContentProperty contentProperty, Map> converterMap, AnalysisContext context, + Integer rowIndex, Integer columnIndex) { + Class clazz; if (field == null) { clazz = String.class; } else { clazz = field.getType(); } - if (clazz == CellData.class) { - Type type = field.getGenericType(); - Class classGeneric; - if (type instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType)type; - classGeneric = (Class)parameterizedType.getActualTypeArguments()[0]; - } else { - classGeneric = String.class; - } - CellData cellDataReturn = new CellData(cellData); + if (clazz == ReadCellData.class) { + Class classGeneric = getClassGeneric(field.getGenericType()); + ReadCellData cellDataReturn = cellData.clone(); cellDataReturn.setData(doConvertToJavaObject(cellData, classGeneric, contentProperty, converterMap, - globalConfiguration, rowIndex, columnIndex)); + context, rowIndex, columnIndex)); return cellDataReturn; } - return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, globalConfiguration, rowIndex, + return doConvertToJavaObject(cellData, clazz, contentProperty, converterMap, context, rowIndex, columnIndex); } + private static Class getClassGeneric(Type type) { + if (!(type instanceof ParameterizedType)) { + return defaultClassGeneric; + } + ParameterizedType parameterizedType = (ParameterizedType)type; + Type[] types = parameterizedType.getActualTypeArguments(); + if (types == null || types.length == 0) { + return defaultClassGeneric; + } + Type actualType = types[0]; + if (!(actualType instanceof Class)) { + return defaultClassGeneric; + } + return (Class)actualType; + } + /** - * * @param cellData * @param clazz * @param contentProperty * @param converterMap - * @param globalConfiguration + * @param context * @param rowIndex * @param columnIndex * @return */ - private static Object doConvertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty, - Map converterMap, GlobalConfiguration globalConfiguration, Integer rowIndex, - Integer columnIndex) { - Converter converter = null; + private static Object doConvertToJavaObject(ReadCellData cellData, Class clazz, + ExcelContentProperty contentProperty, Map> converterMap, AnalysisContext context, + Integer rowIndex, Integer columnIndex) { + Converter converter = null; if (contentProperty != null) { converter = contentProperty.getConverter(); } + + boolean canNotConverterEmpty = cellData.getType() == CellDataTypeEnum.EMPTY + && !(converter instanceof NullableObjectConverter); + if (canNotConverterEmpty) { + return null; + } + if (converter == null) { converter = converterMap.get(ConverterKeyBuild.buildKey(clazz, cellData.getType())); } @@ -129,8 +146,9 @@ public class ConverterUtils { throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty, "Converter not found, convert " + cellData.getType() + " to " + clazz.getName()); } + try { - return converter.convertToJavaData(cellData, contentProperty, globalConfiguration); + return converter.convertToJavaData(new ReadConverterContext<>(cellData, contentProperty, context)); } catch (Exception e) { throw new ExcelDataConvertException(rowIndex, columnIndex, cellData, contentProperty, "Convert data " + cellData + " to " + clazz + " error ", e); diff --git a/src/main/java/com/alibaba/excel/util/DateUtils.java b/src/main/java/com/alibaba/excel/util/DateUtils.java index 815257b9..4a297cf7 100644 --- a/src/main/java/com/alibaba/excel/util/DateUtils.java +++ b/src/main/java/com/alibaba/excel/util/DateUtils.java @@ -3,8 +3,11 @@ package com.alibaba.excel.util; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; @@ -17,16 +20,16 @@ public class DateUtils { /** * Is a cache of dates */ - private static final ThreadLocal> DATE_THREAD_LOCAL = - new ThreadLocal>(); + private static final ThreadLocal> DATE_THREAD_LOCAL = + new ThreadLocal<>(); /** * Is a cache of dates */ private static final ThreadLocal> DATE_FORMAT_THREAD_LOCAL = - new ThreadLocal>(); + new ThreadLocal<>(); /** - * The following patterns are used in {@link #isADateFormat(Integer, String)} + * The following patterns are used in {@link #isADateFormat(Short, String)} */ private static final Pattern date_ptrn1 = Pattern.compile("^\\[\\$\\-.*?\\]"); private static final Pattern date_ptrn2 = Pattern.compile("^\\[[a-zA-Z]+\\]"); @@ -43,11 +46,15 @@ public class DateUtils { public static final String DATE_FORMAT_10 = "yyyy-MM-dd"; public static final String DATE_FORMAT_14 = "yyyyMMddHHmmss"; + public static final String DATE_FORMAT_16 = "yyyy-MM-dd HH:mm"; + public static final String DATE_FORMAT_16_FORWARD_SLASH = "yyyy/MM/dd HH:mm"; public static final String DATE_FORMAT_17 = "yyyyMMdd HH:mm:ss"; public static final String DATE_FORMAT_19 = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_FORMAT_19_FORWARD_SLASH = "yyyy/MM/dd HH:mm:ss"; private static final String MINUS = "-"; + public static String defaultDateFormat = DATE_FORMAT_19; + private DateUtils() {} /** @@ -65,6 +72,25 @@ public class DateUtils { return getCacheDateFormat(dateFormat).parse(dateString); } + /** + * convert string to date + * + * @param dateString + * @param dateFormat + * @param local + * @return + */ + public static LocalDateTime parseLocalDateTime(String dateString, String dateFormat, Locale local) { + if (StringUtils.isEmpty(dateFormat)) { + dateFormat = switchDateFormat(dateString); + } + if (local == null) { + return LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(dateFormat)); + } else { + return LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(dateFormat, local)); + } + } + /** * convert string to date * @@ -82,7 +108,7 @@ public class DateUtils { * @param dateString * @return */ - private static String switchDateFormat(String dateString) { + public static String switchDateFormat(String dateString) { int length = dateString.length(); switch (length) { case 19: @@ -91,6 +117,12 @@ public class DateUtils { } else { return DATE_FORMAT_19_FORWARD_SLASH; } + case 16: + if (dateString.contains(MINUS)) { + return DATE_FORMAT_16; + } else { + return DATE_FORMAT_16_FORWARD_SLASH; + } case 17: return DATE_FORMAT_17; case 14: @@ -123,14 +155,35 @@ public class DateUtils { */ public static String format(Date date, String dateFormat) { if (date == null) { - return ""; + return null; } if (StringUtils.isEmpty(dateFormat)) { - dateFormat = DATE_FORMAT_19; + dateFormat = defaultDateFormat; } return getCacheDateFormat(dateFormat).format(date); } + /** + * Format date + * + * @param date + * @param dateFormat + * @return + */ + public static String format(LocalDateTime date, String dateFormat, Locale local) { + if (date == null) { + return null; + } + if (StringUtils.isEmpty(dateFormat)) { + dateFormat = defaultDateFormat; + } + if (local == null) { + return date.format(DateTimeFormatter.ofPattern(dateFormat)); + } else { + return date.format(DateTimeFormatter.ofPattern(dateFormat, local)); + } + } + private static DateFormat getCacheDateFormat(String dateFormat) { Map dateFormatMap = DATE_FORMAT_THREAD_LOCAL.get(); if (dateFormatMap == null) { @@ -154,13 +207,13 @@ public class DateUtils { * @param formatString * @return */ - public static boolean isADateFormat(Integer formatIndex, String formatString) { + public static boolean isADateFormat(Short formatIndex, String formatString) { if (formatIndex == null) { return false; } - Map isDateCache = DATE_THREAD_LOCAL.get(); + Map isDateCache = DATE_THREAD_LOCAL.get(); if (isDateCache == null) { - isDateCache = new HashMap(); + isDateCache = MapUtils.newHashMap(); DATE_THREAD_LOCAL.set(isDateCache); } else { Boolean isDateCachedData = isDateCache.get(formatIndex); @@ -180,7 +233,7 @@ public class DateUtils { * @param formatString * @return */ - public static boolean isADateFormatUncached(Integer formatIndex, String formatString) { + public static boolean isADateFormatUncached(Short formatIndex, String formatString) { // First up, is this an internal date format? if (isInternalDateFormat(formatIndex)) { return true; @@ -256,9 +309,9 @@ public class DateUtils { /** * Given a format ID this will check whether the format represents an internal excel date format or not. * - * @see #isADateFormat(Integer, String) + * @see #isADateFormat(Short, String) */ - public static boolean isInternalDateFormat(int format) { + public static boolean isInternalDateFormat(short format) { switch (format) { // Internal Date Formats as described on page 427 in // Microsoft Excel Dev's Kit... diff --git a/src/main/java/com/alibaba/excel/util/FieldUtils.java b/src/main/java/com/alibaba/excel/util/FieldUtils.java new file mode 100644 index 00000000..a5c75731 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/FieldUtils.java @@ -0,0 +1,161 @@ +package com.alibaba.excel.util; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Map; + +import com.alibaba.excel.metadata.NullObject; +import com.alibaba.excel.write.metadata.RowData; + +import net.sf.cglib.beans.BeanMap; + +/** + * Field utils + * + * @author Jiaju Zhuang + **/ +public class FieldUtils { + + public static Class nullObjectClass = NullObject.class; + + private static final int START_RESOLVE_FIELD_LENGTH = 2; + + public static Class getFieldClass(Map dataMap, String filedName) { + if (dataMap instanceof BeanMap) { + return ((BeanMap)dataMap).getPropertyType(filedName); + } + Object value = dataMap.get(filedName); + if (value != null) { + return value.getClass(); + } + return nullObjectClass; + } + + public static Class getFieldClass(RowData rowData, int dataIndex) { + Object value = rowData.get(dataIndex); + if (value != null) { + return value.getClass(); + } + return nullObjectClass; + } + + /** + * Parsing the name matching cglib。 + *
+     *     null -> null
+     *     string1 -> string1
+     *     String2 -> string2
+     *     sTring3 -> STring3
+     *     STring4 -> STring4
+     *     STRING5 -> STRING5
+     *     STRing6 -> STRing6
+     * 
+ * + * @param field field + * @return field name. + */ + public static String resolveCglibFieldName(Field field) { + if (field == null) { + return null; + } + String fieldName = field.getName(); + if (StringUtils.isBlank(fieldName) || fieldName.length() < START_RESOLVE_FIELD_LENGTH) { + return fieldName; + } + char firstChar = fieldName.charAt(0); + char secondChar = fieldName.charAt(1); + if (Character.isUpperCase(firstChar) == Character.isUpperCase(secondChar)) { + return fieldName; + } + if (Character.isUpperCase(firstChar)) { + return buildFieldName(Character.toLowerCase(firstChar), fieldName); + } + return buildFieldName(Character.toUpperCase(firstChar), fieldName); + } + + private static String buildFieldName(char firstChar, String fieldName) { + return firstChar + fieldName.substring(1); + } + + /** + * Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered. + * + * @param cls the {@link Class} to reflect, must not be {@code null} + * @param fieldName the field name to obtain + * @return the Field object + * @throws IllegalArgumentException if the class is {@code null}, or the field name is blank or empty + */ + public static Field getField(final Class cls, final String fieldName) { + final Field field = getField(cls, fieldName, false); + MemberUtils.setAccessibleWorkaround(field); + return field; + } + + /** + * Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be + * considered. + * + * @param cls the {@link Class} to reflect, must not be {@code null} + * @param fieldName the field name to obtain + * @param forceAccess whether to break scope restrictions using the + * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will + * only + * match {@code public} fields. + * @return the Field object + * @throws NullPointerException if the class is {@code null} + * @throws IllegalArgumentException if the field name is blank or empty or is matched at multiple places + * in the inheritance hierarchy + */ + public static Field getField(final Class cls, final String fieldName, final boolean forceAccess) { + Validate.isTrue(cls != null, "The class must not be null"); + Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty"); + // FIXME is this workaround still needed? lang requires Java 6 + // Sun Java 1.3 has a bugged implementation of getField hence we write the + // code ourselves + + // getField() will return the Field object with the declaring class + // set correctly to the class that declares the field. Thus requesting the + // field on a subclass will return the field from the superclass. + // + // priority order for lookup: + // searchclass private/protected/package/public + // superclass protected/package/public + // private/different package blocks access to further superclasses + // implementedinterface public + + // check up the superclass hierarchy + for (Class acls = cls; acls != null; acls = acls.getSuperclass()) { + try { + final Field field = acls.getDeclaredField(fieldName); + // getDeclaredField checks for non-public scopes as well + // and it returns accurate results + if (!Modifier.isPublic(field.getModifiers())) { + if (forceAccess) { + field.setAccessible(true); + } else { + continue; + } + } + return field; + } catch (final NoSuchFieldException ex) { // NOPMD + // ignore + } + } + // check the public interface case. This must be manually searched for + // incase there is a public supersuperclass field hidden by a private/package + // superclass field. + Field match = null; + for (final Class class1 : ClassUtils.getAllInterfaces(cls)) { + try { + final Field test = class1.getField(fieldName); + Validate.isTrue(match == null, "Reference to field %s is ambiguous relative to %s" + + "; a matching field exists on two or more implemented interfaces.", fieldName, cls); + match = test; + } catch (final NoSuchFieldException ex) { // NOPMD + // ignore + } + } + return match; + } + +} diff --git a/src/main/java/com/alibaba/excel/util/FileTypeUtils.java b/src/main/java/com/alibaba/excel/util/FileTypeUtils.java new file mode 100644 index 00000000..45de5059 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/FileTypeUtils.java @@ -0,0 +1,59 @@ +package com.alibaba.excel.util; + +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.excel.metadata.data.ImageData.ImageType; + +/** + * file type utils + * + * @author Jiaju Zhuang + */ +public class FileTypeUtils { + + private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', + 'f'}; + private static final int IMAGE_TYPE_MARK_LENGTH = 28; + + private static final Map FILE_TYPE_MAP; + + /** + * Default image type + */ + public static ImageType defaultImageType = ImageType.PICTURE_TYPE_PNG; + + static { + FILE_TYPE_MAP = new HashMap<>(); + FILE_TYPE_MAP.put("ffd8ff", ImageType.PICTURE_TYPE_JPEG); + FILE_TYPE_MAP.put("89504e47", ImageType.PICTURE_TYPE_PNG); + } + + public static int getImageTypeFormat(byte[] image) { + ImageType imageType = getImageType(image); + if (imageType != null) { + return imageType.getValue(); + } + return defaultImageType.getValue(); + } + + public static ImageType getImageType(byte[] image) { + if (image == null || image.length <= IMAGE_TYPE_MARK_LENGTH) { + return null; + } + byte[] typeMarkByte = new byte[IMAGE_TYPE_MARK_LENGTH]; + System.arraycopy(image, 0, typeMarkByte, 0, IMAGE_TYPE_MARK_LENGTH); + return FILE_TYPE_MAP.get(encodeHexStr(typeMarkByte)); + } + + private static String encodeHexStr(byte[] data) { + final int len = data.length; + final char[] out = new char[len << 1]; + // two characters from the hex value. + for (int i = 0, j = 0; i < len; i++) { + out[j++] = DIGITS[(0xF0 & data[i]) >>> 4]; + out[j++] = DIGITS[0x0F & data[i]]; + } + return new String(out); + } +} diff --git a/src/main/java/com/alibaba/excel/util/FileUtils.java b/src/main/java/com/alibaba/excel/util/FileUtils.java index 20b16bc6..bc6b5d8a 100644 --- a/src/main/java/com/alibaba/excel/util/FileUtils.java +++ b/src/main/java/com/alibaba/excel/util/FileUtils.java @@ -9,12 +9,12 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; -import org.apache.poi.util.DefaultTempFileCreationStrategy; -import org.apache.poi.util.TempFile; - import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelCommonException; +import org.apache.poi.util.DefaultTempFileCreationStrategy; +import org.apache.poi.util.TempFile; + /** * * @author jipengfei @@ -100,10 +100,21 @@ public class FileUtils { /** * Write inputStream to file * - * @param file - * @param inputStream + * @param file file + * @param inputStream inputStream */ public static void writeToFile(File file, InputStream inputStream) { + writeToFile(file, inputStream, true); + } + + /** + * Write inputStream to file + * + * @param file file + * @param inputStream inputStream + * @param closeInputStream closeInputStream + */ + public static void writeToFile(File file, InputStream inputStream, boolean closeInputStream) { OutputStream outputStream = null; try { outputStream = new FileOutputStream(file); @@ -122,7 +133,7 @@ public class FileUtils { throw new ExcelAnalysisException("Can not close 'outputStream'!", e); } } - if (inputStream != null) { + if (inputStream != null && closeInputStream) { try { inputStream.close(); } catch (IOException e) { @@ -132,6 +143,7 @@ public class FileUtils { } } + public static void createPoiFilesDirectory() { File poiFilesPathFile = new File(poiFilesPath); createDirectory(poiFilesPathFile); diff --git a/src/main/java/com/alibaba/excel/util/IntUtils.java b/src/main/java/com/alibaba/excel/util/IntUtils.java new file mode 100644 index 00000000..6d2e244c --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/IntUtils.java @@ -0,0 +1,39 @@ +package com.alibaba.excel.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * Int utils + * + * @author Jiaju Zhuang + **/ +public class IntUtils { + private IntUtils() {} + + + /** + * The largest power of two that can be represented as an {@code int}. + * + * @since 10.0 + */ + public static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2); + + /** + * Returns the {@code int} nearest in value to {@code value}. + * + * @param value any {@code long} value + * @return the same value cast to {@code int} if it is in the range of the {@code int} type, + * {@link Integer#MAX_VALUE} if it is too large, or {@link Integer#MIN_VALUE} if it is too + * small + */ + public static int saturatedCast(long value) { + if (value > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } + if (value < Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } + return (int) value; + } +} diff --git a/src/main/java/com/alibaba/excel/util/ListUtils.java b/src/main/java/com/alibaba/excel/util/ListUtils.java new file mode 100644 index 00000000..e64acb36 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/ListUtils.java @@ -0,0 +1,136 @@ +package com.alibaba.excel.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import lombok.NonNull; +import org.apache.commons.compress.utils.Iterators; + +/** + * List utils + * + * @author Jiaju Zhuang + **/ +public class ListUtils { + private ListUtils() {} + + /** + * Creates a mutable, empty {@code ArrayList} instance (for Java 6 and earlier). + * + *

Note for Java 7 and later: this method is now unnecessary and should be treated as + * deprecated. Instead, use the {@code ArrayList} {@linkplain ArrayList#ArrayList() constructor} + * directly, taking advantage of the new "diamond" syntax. + */ + public static ArrayList newArrayList() { + return new ArrayList<>(); + } + + /** + * Creates a mutable {@code ArrayList} instance containing the given elements. + * + */ + public static ArrayList newArrayList(E... elements) { + checkNotNull(elements); + // Avoid integer overflow when a large array is passed in + int capacity = computeArrayListCapacity(elements.length); + ArrayList list = new ArrayList<>(capacity); + Collections.addAll(list, elements); + return list; + } + + + /** + * Creates a mutable {@code ArrayList} instance containing the given elements; a very thin + * shortcut for creating an empty list and then calling {@link Iterators#addAll}. + * + */ + public static ArrayList newArrayList(Iterator elements) { + ArrayList list = newArrayList(); + Iterators.addAll(list, elements); + return list; + } + + /** + * Creates a mutable {@code ArrayList} instance containing the given elements; + * + * + *

Note for Java 7 and later: if {@code elements} is a {@link Collection}, you don't + * need this method. Use the {@code ArrayList} {@linkplain ArrayList#ArrayList(Collection) + * constructor} directly, taking advantage of the new "diamond" + * syntax. + */ + public static ArrayList newArrayList(Iterable elements) { + checkNotNull(elements); // for GWT + // Let ArrayList's sizing logic work, if possible + return (elements instanceof Collection) + ? new ArrayList<>((Collection)elements) + : newArrayList(elements.iterator()); + } + + /** + * Creates an {@code ArrayList} instance backed by an array with the specified initial size; + * simply delegates to {@link ArrayList#ArrayList(int)}. + * + *

Note for Java 7 and later: this method is now unnecessary and should be treated as + * deprecated. Instead, use {@code new }{@link ArrayList#ArrayList(int) ArrayList}{@code <>(int)} + * directly, taking advantage of the new "diamond" syntax. + * (Unlike here, there is no risk of overload ambiguity, since the {@code ArrayList} constructors + * very wisely did not accept varargs.) + * + * @param initialArraySize the exact size of the initial backing array for the returned array list + * ({@code ArrayList} documentation calls this value the "capacity") + * @return a new, empty {@code ArrayList} which is guaranteed not to resize itself unless its size + * reaches {@code initialArraySize + 1} + * @throws IllegalArgumentException if {@code initialArraySize} is negative + */ + public static ArrayList newArrayListWithCapacity(int initialArraySize) { + checkNonnegative(initialArraySize, "initialArraySize"); + return new ArrayList<>(initialArraySize); + } + + /** + * Creates an {@code ArrayList} instance to hold {@code estimatedSize} elements, plus an + * unspecified amount of padding; you almost certainly mean to call {@link + * #newArrayListWithCapacity} (see that method for further advice on usage). + * + *

Note: This method will soon be deprecated. Even in the rare case that you do want + * some amount of padding, it's best if you choose your desired amount explicitly. + * + * @param estimatedSize an estimate of the eventual {@link List#size()} of the new list + * @return a new, empty {@code ArrayList}, sized appropriately to hold the estimated number of + * elements + * @throws IllegalArgumentException if {@code estimatedSize} is negative + */ + public static ArrayList newArrayListWithExpectedSize(int estimatedSize) { + return new ArrayList<>(computeArrayListCapacity(estimatedSize)); + } + + static int computeArrayListCapacity(int arraySize) { + checkNonnegative(arraySize, "arraySize"); + return IntUtils.saturatedCast(5L + arraySize + (arraySize / 10)); + } + + static int checkNonnegative(int value, String name) { + if (value < 0) { + throw new IllegalArgumentException(name + " cannot be negative but was: " + value); + } + return value; + } + + /** + * Ensures that an object reference passed as a parameter to the calling method is not null. + * + * @param reference an object reference + * @return the non-null reference that was validated + * @throws NullPointerException if {@code reference} is null + */ + public static T checkNotNull(T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } +} diff --git a/src/main/java/com/alibaba/excel/util/MapUtils.java b/src/main/java/com/alibaba/excel/util/MapUtils.java new file mode 100644 index 00000000..8ad5145a --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/MapUtils.java @@ -0,0 +1,112 @@ +package com.alibaba.excel.util; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.TreeMap; + +/** + * Map utils + * + * @author Jiaju Zhuang + **/ +public class MapUtils { + + private MapUtils() {} + + + /** + * Creates a mutable, empty {@code HashMap} instance. + * + *

Note: if mutability is not required, use ImmutableMap.of() instead. + * + *

Note: if {@code K} is an {@code enum} type, use newEnumMap instead. + * + *

Note for Java 7 and later: this method is now unnecessary and should be treated as + * deprecated. Instead, use the {@code HashMap} constructor directly, taking advantage of the new + * "diamond" syntax. + * + * @return a new, empty {@code HashMap} + */ + public static HashMap newHashMap() { + return new HashMap<>(16); + } + + /** + * Creates a mutable, empty {@code TreeMap} instance using the natural ordering of its + * elements. + * + *

Note: if mutability is not required, use ImmutableSortedMap.of() instead. + * + *

Note for Java 7 and later: this method is now unnecessary and should be treated as + * deprecated. Instead, use the {@code TreeMap} constructor directly, taking advantage of the new + * "diamond" syntax. + * + * @return a new, empty {@code TreeMap} + */ + public static TreeMap newTreeMap() { + return new TreeMap<>(); + } + + /** + * Creates a {@code HashMap} instance, with a high enough "initial capacity" that it should + * hold {@code expectedSize} elements without growth. This behavior cannot be broadly guaranteed, + * but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the method + * isn't inadvertently oversizing the returned map. + * + * @param expectedSize the number of entries you expect to add to the returned map + * @return a new, empty {@code HashMap} with enough capacity to hold {@code expectedSize} entries + * without resizing + * @throws IllegalArgumentException if {@code expectedSize} is negative + */ + public static HashMap newHashMapWithExpectedSize(int expectedSize) { + return new HashMap<>(capacity(expectedSize)); + } + + /** + * Creates a mutable, empty, insertion-ordered {@code LinkedHashMap} instance. + * + *

Note: if mutability is not required, use {@link ImmutableMap#of()} instead. + * + *

Note for Java 7 and later: this method is now unnecessary and should be treated as + * deprecated. Instead, use the {@code LinkedHashMap} constructor directly, taking advantage of + * the new "diamond" syntax. + * + * @return a new, empty {@code LinkedHashMap} + */ + public static LinkedHashMap newLinkedHashMap() { + return new LinkedHashMap<>(); + } + + /** + * Creates a {@code LinkedHashMap} instance, with a high enough "initial capacity" that it + * should hold {@code expectedSize} elements without growth. This behavior cannot be + * broadly guaranteed, but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed + * that the method isn't inadvertently oversizing the returned map. + * + * @param expectedSize the number of entries you expect to add to the returned map + * @return a new, empty {@code LinkedHashMap} with enough capacity to hold {@code expectedSize} + * entries without resizing + * @throws IllegalArgumentException if {@code expectedSize} is negative + * @since 19.0 + */ + public static LinkedHashMap newLinkedHashMapWithExpectedSize(int expectedSize) { + return new LinkedHashMap<>(capacity(expectedSize)); + } + + /** + * Returns a capacity that is sufficient to keep the map from being resized as long as it grows no + * larger than expectedSize and the load factor is ≥ its default (0.75). + */ + static int capacity(int expectedSize) { + if (expectedSize < 3) { + return expectedSize + 1; + } + if (expectedSize < IntUtils.MAX_POWER_OF_TWO) { + // This is the calculation used in JDK8 to resize when a putAll + // happens; it seems to be the most conservative calculation we + // can make. 0.75 is the default load factor. + return (int)((float)expectedSize / 0.75F + 1.0F); + } + return Integer.MAX_VALUE; + } +} diff --git a/src/main/java/com/alibaba/excel/util/MemberUtils.java b/src/main/java/com/alibaba/excel/util/MemberUtils.java new file mode 100644 index 00000000..6bcfaac6 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/MemberUtils.java @@ -0,0 +1,54 @@ +package com.alibaba.excel.util; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Member; +import java.lang.reflect.Modifier; + +/** + * Member utils. + * + * @author Jiaju Zhuang + */ +public class MemberUtils { + + private static final int ACCESS_TEST = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; + + + /** + * XXX Default access superclass workaround. + * + * When a {@code public} class has a default access superclass with {@code public} members, + * these members are accessible. Calling them from compiled code works fine. + * Unfortunately, on some JVMs, using reflection to invoke these members + * seems to (wrongly) prevent access even when the modifier is {@code public}. + * Calling {@code setAccessible(true)} solves the problem but will only work from + * sufficiently privileged code. Better workarounds would be gratefully + * accepted. + * @param o the AccessibleObject to set as accessible + * @return a boolean indicating whether the accessibility of the object was set to true. + */ + static boolean setAccessibleWorkaround(final AccessibleObject o) { + if (o == null || o.isAccessible()) { + return false; + } + final Member m = (Member) o; + if (!o.isAccessible() && Modifier.isPublic(m.getModifiers()) && isPackageAccess(m.getDeclaringClass().getModifiers())) { + try { + o.setAccessible(true); + return true; + } catch (final SecurityException e) { // NOPMD + // ignore in favor of subsequent IllegalAccessException + } + } + return false; + } + + /** + * Returns whether a given set of modifiers implies package access. + * @param modifiers to test + * @return {@code true} unless {@code package}/{@code protected}/{@code private} modifier detected + */ + static boolean isPackageAccess(final int modifiers) { + return (modifiers & ACCESS_TEST) == 0; + } +} diff --git a/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java b/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java index b4ba5b02..83d7a23f 100644 --- a/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java +++ b/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java @@ -1,9 +1,10 @@ package com.alibaba.excel.util; import java.math.BigDecimal; +import java.util.Locale; -import com.alibaba.excel.metadata.format.DataFormatter; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.format.DataFormatter; /** * Convert number data, including date. @@ -26,15 +27,34 @@ public class NumberDataFormatterUtils { * @param globalConfiguration * @return */ - public static String format(BigDecimal data, Integer dataFormat, String dataFormatString, + public static String format(BigDecimal data, Short dataFormat, String dataFormatString, GlobalConfiguration globalConfiguration) { + if (globalConfiguration == null) { + return format(data, dataFormat, dataFormatString, null, null, null); + } + return format(data, dataFormat, dataFormatString, globalConfiguration.getUse1904windowing(), + globalConfiguration.getLocale(), globalConfiguration.getUseScientificFormat()); + } + + /** + * Format number data. + * + * @param data + * @param dataFormat Not null. + * @param dataFormatString + * @param use1904windowing + * @param locale + * @param useScientificFormat + * @return + */ + public static String format(BigDecimal data, Short dataFormat, String dataFormatString, Boolean use1904windowing, + Locale locale, Boolean useScientificFormat) { DataFormatter dataFormatter = DATA_FORMATTER_THREAD_LOCAL.get(); if (dataFormatter == null) { - dataFormatter = new DataFormatter(globalConfiguration); + dataFormatter = new DataFormatter(use1904windowing, locale, useScientificFormat); DATA_FORMATTER_THREAD_LOCAL.set(dataFormatter); } return dataFormatter.format(data, dataFormat, dataFormatString); - } public static void removeThreadLocalCache() { diff --git a/src/main/java/com/alibaba/excel/util/NumberUtils.java b/src/main/java/com/alibaba/excel/util/NumberUtils.java index 4257ff44..ea2635e6 100644 --- a/src/main/java/com/alibaba/excel/util/NumberUtils.java +++ b/src/main/java/com/alibaba/excel/util/NumberUtils.java @@ -5,7 +5,7 @@ import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.ParseException; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -46,8 +46,24 @@ public class NumberUtils { * @param contentProperty * @return */ - public static CellData formatToCellData(Number num, ExcelContentProperty contentProperty) { - return new CellData(format(num, contentProperty)); + public static WriteCellData formatToCellDataString(Number num, ExcelContentProperty contentProperty) { + return new WriteCellData<>(format(num, contentProperty)); + } + + /** + * format + * + * @param num + * @param contentProperty + * @return + */ + public static WriteCellData formatToCellData(Number num, ExcelContentProperty contentProperty) { + WriteCellData cellData = new WriteCellData<>(BigDecimal.valueOf(num.doubleValue())); + if (contentProperty != null && contentProperty.getNumberFormatProperty() != null + && StringUtils.isNotBlank(contentProperty.getNumberFormatProperty().getFormat())) { + WorkBookUtil.fillDataFormat(cellData, contentProperty.getNumberFormatProperty().getFormat(), null); + } + return cellData; } /** diff --git a/src/main/java/com/alibaba/excel/util/PositionUtils.java b/src/main/java/com/alibaba/excel/util/PositionUtils.java index a527ae1f..48c5cde5 100644 --- a/src/main/java/com/alibaba/excel/util/PositionUtils.java +++ b/src/main/java/com/alibaba/excel/util/PositionUtils.java @@ -1,10 +1,21 @@ package com.alibaba.excel.util; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.poi.ss.util.CellReference; + /** * @author jipengfei */ public class PositionUtils { + private static final Pattern CELL_REF_PATTERN = Pattern.compile("(\\$?[A-Z]+)?" + "(\\$?[0-9]+)?", + Pattern.CASE_INSENSITIVE); + private static final char SHEET_NAME_DELIMITER = '!'; + private static final char REDUNDANT_CHARACTERS = '$'; + private PositionUtils() {} public static int getRowByRowTagt(String rowTagt) { @@ -30,35 +41,37 @@ public class PositionUtils { } public static int getRow(String currentCellIndex) { - int row = 0; - if (currentCellIndex != null) { - String rowStr = currentCellIndex.replaceAll("[A-Z]", "").replaceAll("[a-z]", ""); - row = Integer.parseInt(rowStr) - 1; - } - return row; - } - - public static int getCol(String currentCellIndex) { - int col = 0; if (currentCellIndex != null) { - - char[] currentIndex = currentCellIndex.replaceAll("[0-9]", "").toCharArray(); - for (int i = 0; i < currentIndex.length; i++) { - col += (currentIndex[i] - '@') * Math.pow(26, (currentIndex.length - i - 1)); + int plingPos = currentCellIndex.lastIndexOf(SHEET_NAME_DELIMITER); + String cell = currentCellIndex.substring(plingPos + 1).toUpperCase(Locale.ROOT); + Matcher matcher = CELL_REF_PATTERN.matcher(cell); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid CellReference: " + currentCellIndex); } + String row = matcher.group(2); + return Integer.parseInt(row) - 1; } - return col - 1; + return -1; } public static int getCol(String currentCellIndex, Integer before) { - int col = 0; if (currentCellIndex != null) { + int plingPos = currentCellIndex.lastIndexOf(SHEET_NAME_DELIMITER); + String cell = currentCellIndex.substring(plingPos + 1).toUpperCase(Locale.ROOT); + Matcher matcher = CELL_REF_PATTERN.matcher(cell); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid CellReference: " + currentCellIndex); + } + String col = matcher.group(1); - char[] currentIndex = currentCellIndex.replaceAll("[0-9]", "").toCharArray(); - for (int i = 0; i < currentIndex.length; i++) { - col += (currentIndex[i] - '@') * Math.pow(26, (currentIndex.length - i - 1)); + if (col.length() > 0 && col.charAt(0) == REDUNDANT_CHARACTERS) { + col = col.substring(1); + } + if (col.length() == 0) { + return -1; + } else { + return CellReference.convertColStringToIndex(col); } - return col - 1; } else { if (before == null) { before = -1; diff --git a/src/main/java/com/alibaba/excel/util/StringUtils.java b/src/main/java/com/alibaba/excel/util/StringUtils.java index 948ae652..6c636908 100644 --- a/src/main/java/com/alibaba/excel/util/StringUtils.java +++ b/src/main/java/com/alibaba/excel/util/StringUtils.java @@ -6,11 +6,227 @@ package com.alibaba.excel.util; * @author jipengfei */ public class StringUtils { + private StringUtils() {} + + /** + * A String for a space character. + */ + public static final String SPACE = " "; + + /** + * The empty String {@code ""}. + */ public static final String EMPTY = ""; - private StringUtils() {} + /** + *

Checks if a CharSequence is empty ("") or null.

+ * + *
+     * StringUtils.isEmpty(null)      = true
+     * StringUtils.isEmpty("")        = true
+     * StringUtils.isEmpty(" ")       = false
+     * StringUtils.isEmpty("bob")     = false
+     * StringUtils.isEmpty("  bob  ") = false
+     * 
+ * + *

NOTE: This method changed in Lang version 2.0. + * It no longer trims the CharSequence. + * That functionality is available in isBlank().

+ * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is empty or null + */ + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; + } + + /** + *

Checks if a CharSequence is empty (""), null or whitespace only.

+ * + *

Whitespace is defined by {@link Character#isWhitespace(char)}.

+ * + *
+     * StringUtils.isBlank(null)      = true
+     * StringUtils.isBlank("")        = true
+     * StringUtils.isBlank(" ")       = true
+     * StringUtils.isBlank("bob")     = false
+     * StringUtils.isBlank("  bob  ") = false
+     * 
+ * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is null, empty or whitespace only + */ + public static boolean isBlank(final CharSequence cs) { + int strLen; + if (cs == null || (strLen = cs.length()) == 0) { + return true; + } + for (int i = 0; i < strLen; i++) { + if (!Character.isWhitespace(cs.charAt(i))) { + return false; + } + } + return true; + } + + /** + *

Checks if a CharSequence is not empty (""), not null and not whitespace only.

+ * + *

Whitespace is defined by {@link Character#isWhitespace(char)}.

+ * + *
+     * StringUtils.isNotBlank(null)      = false
+     * StringUtils.isNotBlank("")        = false
+     * StringUtils.isNotBlank(" ")       = false
+     * StringUtils.isNotBlank("bob")     = true
+     * StringUtils.isNotBlank("  bob  ") = true
+     * 
+ * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is + * not empty and not null and not whitespace only + * @since 2.0 + * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) + */ + public static boolean isNotBlank(final CharSequence cs) { + return !isBlank(cs); + } + + /** + *

Compares two CharSequences, returning {@code true} if they represent + * equal sequences of characters.

+ * + *

{@code null}s are handled without exceptions. Two {@code null} + * references are considered to be equal. The comparison is case sensitive.

+ * + *
+     * StringUtils.equals(null, null)   = true
+     * StringUtils.equals(null, "abc")  = false
+     * StringUtils.equals("abc", null)  = false
+     * StringUtils.equals("abc", "abc") = true
+     * StringUtils.equals("abc", "ABC") = false
+     * 
+ * + * @param cs1 the first CharSequence, may be {@code null} + * @param cs2 the second CharSequence, may be {@code null} + * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} + * @see Object#equals(Object) + * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) + */ + public static boolean equals(final CharSequence cs1, final CharSequence cs2) { + if (cs1 == cs2) { + return true; + } + if (cs1 == null || cs2 == null) { + return false; + } + if (cs1.length() != cs2.length()) { + return false; + } + if (cs1 instanceof String && cs2 instanceof String) { + return cs1.equals(cs2); + } + return regionMatches(cs1, false, 0, cs2, 0, cs1.length()); + } + + /** + * Green implementation of regionMatches. + * + * @param cs the {@code CharSequence} to be processed + * @param ignoreCase whether or not to be case insensitive + * @param thisStart the index to start on the {@code cs} CharSequence + * @param substring the {@code CharSequence} to be looked for + * @param start the index to start on the {@code substring} CharSequence + * @param length character length of the region + * @return whether the region matched + */ + public static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart, + final CharSequence substring, final int start, final int length) { + if (cs instanceof String && substring instanceof String) { + return ((String)cs).regionMatches(ignoreCase, thisStart, (String)substring, start, length); + } + int index1 = thisStart; + int index2 = start; + int tmpLen = length; + + // Extract these first so we detect NPEs the same as the java.lang.String version + final int srcLen = cs.length() - thisStart; + final int otherLen = substring.length() - start; + + // Check for invalid parameters + if (thisStart < 0 || start < 0 || length < 0) { + return false; + } + + // Check that the regions are long enough + if (srcLen < length || otherLen < length) { + return false; + } + + while (tmpLen-- > 0) { + final char c1 = cs.charAt(index1++); + final char c2 = substring.charAt(index2++); + + if (c1 == c2) { + continue; + } + + if (!ignoreCase) { + return false; + } + + // The same check as in String.regionMatches(): + if (Character.toUpperCase(c1) != Character.toUpperCase(c2) + && Character.toLowerCase(c1) != Character.toLowerCase(c2)) { + return false; + } + } + + return true; + } + - public static boolean isEmpty(Object str) { - return (str == null || EMPTY.equals(str)); + /** + *

Checks if the CharSequence contains only Unicode digits. + * A decimal point is not a Unicode digit and returns false.

+ * + *

{@code null} will return {@code false}. + * An empty CharSequence (length()=0) will return {@code false}.

+ * + *

Note that the method does not allow for a leading sign, either positive or negative. + * Also, if a String passes the numeric test, it may still generate a NumberFormatException + * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range + * for int or long respectively.

+ * + *
+     * StringUtils.isNumeric(null)   = false
+     * StringUtils.isNumeric("")     = false
+     * StringUtils.isNumeric("  ")   = false
+     * StringUtils.isNumeric("123")  = true
+     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
+     * StringUtils.isNumeric("12 3") = false
+     * StringUtils.isNumeric("ab2c") = false
+     * StringUtils.isNumeric("12-3") = false
+     * StringUtils.isNumeric("12.3") = false
+     * StringUtils.isNumeric("-123") = false
+     * StringUtils.isNumeric("+123") = false
+     * 
+ * + * @param cs the CharSequence to check, may be null + * @return {@code true} if only contains digits, and is non-null + * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) + * @since 3.0 Changed "" to return false and not true + */ + public static boolean isNumeric(final CharSequence cs) { + if (isEmpty(cs)) { + return false; + } + final int sz = cs.length(); + for (int i = 0; i < sz; i++) { + if (!Character.isDigit(cs.charAt(i))) { + return false; + } + } + return true; } } diff --git a/src/main/java/com/alibaba/excel/util/StyleUtil.java b/src/main/java/com/alibaba/excel/util/StyleUtil.java index d0e1bd32..70c7ac7a 100644 --- a/src/main/java/com/alibaba/excel/util/StyleUtil.java +++ b/src/main/java/com/alibaba/excel/util/StyleUtil.java @@ -1,16 +1,25 @@ package com.alibaba.excel.util; -import org.apache.poi.ss.usermodel.BorderStyle; +import com.alibaba.excel.constant.BuiltinFormats; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.data.HyperlinkData; +import com.alibaba.excel.metadata.data.RichTextStringData; +import com.alibaba.excel.metadata.data.RichTextStringData.IntervalFont; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.common.usermodel.HyperlinkType; +import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Workbook; - -import com.alibaba.excel.write.metadata.style.WriteCellStyle; -import com.alibaba.excel.write.metadata.style.WriteFont; +import org.apache.poi.util.Units; +import org.apache.poi.xssf.usermodel.XSSFRichTextString; /** * @author jipengfei @@ -20,62 +29,22 @@ public class StyleUtil { private StyleUtil() {} /** - * @param workbook - * @return - */ - public static CellStyle buildDefaultCellStyle(Workbook workbook) { - CellStyle newCellStyle = workbook.createCellStyle(); - newCellStyle.setWrapText(true); - newCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); - newCellStyle.setAlignment(HorizontalAlignment.CENTER); - newCellStyle.setLocked(true); - newCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); - newCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); - newCellStyle.setBorderTop(BorderStyle.THIN); - newCellStyle.setBorderBottom(BorderStyle.THIN); - newCellStyle.setBorderLeft(BorderStyle.THIN); - newCellStyle.setBorderRight(BorderStyle.THIN); - return newCellStyle; - } - - /** - * Build head cell style - * - * @param workbook - * @param writeCellStyle - * @return - */ - public static CellStyle buildHeadCellStyle(Workbook workbook, WriteCellStyle writeCellStyle) { - CellStyle cellStyle = buildDefaultCellStyle(workbook); - if (writeCellStyle == null) { - return cellStyle; - } - buildCellStyle(workbook, cellStyle, writeCellStyle, true); - return cellStyle; - } - - /** - * Build content cell style + * Build cell style * * @param workbook * @param writeCellStyle * @return */ - public static CellStyle buildContentCellStyle(Workbook workbook, WriteCellStyle writeCellStyle) { + public static CellStyle buildCellStyle(Workbook workbook, WriteCellStyle writeCellStyle) { CellStyle cellStyle = workbook.createCellStyle(); if (writeCellStyle == null) { return cellStyle; } - buildCellStyle(workbook, cellStyle, writeCellStyle, false); + buildCellStyle(cellStyle, writeCellStyle); return cellStyle; } - private static void buildCellStyle(Workbook workbook, CellStyle cellStyle, WriteCellStyle writeCellStyle, - boolean isHead) { - buildFont(workbook, cellStyle, writeCellStyle.getWriteFont(), isHead); - if (writeCellStyle.getDataFormat() != null) { - cellStyle.setDataFormat(writeCellStyle.getDataFormat()); - } + private static void buildCellStyle(CellStyle cellStyle, WriteCellStyle writeCellStyle) { if (writeCellStyle.getHidden() != null) { cellStyle.setHidden(writeCellStyle.getHidden()); } @@ -138,21 +107,24 @@ public class StyleUtil { } } - private static void buildFont(Workbook workbook, CellStyle cellStyle, WriteFont writeFont, boolean isHead) { - Font font = null; - if (isHead) { - font = workbook.createFont(); - font.setFontName("宋体"); - font.setFontHeightInPoints((short)14); - font.setBold(true); - cellStyle.setFont(font); - } - if (writeFont == null) { - return; - } - if (!isHead) { - font = workbook.createFont(); - cellStyle.setFont(font); + public static short buildDataFormat(Workbook workbook, DataFormatData dataFormatData) { + if (dataFormatData == null) { + return BuiltinFormats.GENERAL; + } + if (dataFormatData.getIndex() != null && dataFormatData.getIndex() >= 0) { + return dataFormatData.getIndex(); + } + if (StringUtils.isNotBlank(dataFormatData.getFormat())) { + DataFormat dataFormatCreate = workbook.createDataFormat(); + return dataFormatCreate.getFormat(dataFormatData.getFormat()); + } + return BuiltinFormats.GENERAL; + } + + public static Font buildFont(Workbook workbook, WriteFont writeFont) { + Font font = workbook.createFont(); + if (writeFont == null || font == null) { + return font; } if (writeFont.getFontName() != null) { font.setFontName(writeFont.getFontName()); @@ -181,6 +153,57 @@ public class StyleUtil { if (writeFont.getBold() != null) { font.setBold(writeFont.getBold()); } + return font; + } + + public static RichTextString buildRichTextString(WriteWorkbookHolder writeWorkbookHolder, + RichTextStringData richTextStringData) { + if (richTextStringData == null) { + return null; + } + RichTextString richTextString; + if (writeWorkbookHolder.getExcelType() == ExcelTypeEnum.XLSX) { + richTextString = new XSSFRichTextString(richTextStringData.getTextString()); + } else { + richTextString = new HSSFRichTextString(richTextStringData.getTextString()); + } + if (richTextStringData.getWriteFont() != null) { + richTextString.applyFont(writeWorkbookHolder.createFont(richTextStringData.getWriteFont())); + } + if (CollectionUtils.isNotEmpty(richTextStringData.getIntervalFontList())) { + for (IntervalFont intervalFont : richTextStringData.getIntervalFontList()) { + richTextString.applyFont(intervalFont.getStartIndex(), intervalFont.getEndIndex(), + writeWorkbookHolder.createFont(intervalFont.getWriteFont())); + } + } + return richTextString; + } + + public static HyperlinkType getHyperlinkType(HyperlinkData.HyperlinkType hyperlinkType) { + if (hyperlinkType == null) { + return HyperlinkType.NONE; + } + return hyperlinkType.getValue(); + } + + public static int getCoordinate(Integer coordinate) { + if (coordinate == null) { + return 0; + } + return Units.toEMU(coordinate); + } + + public static int getCellCoordinate(Integer currentCoordinate, Integer absoluteCoordinate, + Integer relativeCoordinate) { + if (absoluteCoordinate != null && absoluteCoordinate > 0) { + return absoluteCoordinate; + } + if (relativeCoordinate != null) { + return currentCoordinate + relativeCoordinate; + } + return currentCoordinate; } } + + diff --git a/src/main/java/com/alibaba/excel/util/Validate.java b/src/main/java/com/alibaba/excel/util/Validate.java new file mode 100644 index 00000000..6207bb1a --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/Validate.java @@ -0,0 +1,151 @@ +package com.alibaba.excel.util; + +import java.util.Objects; + +/** + * Validate + * + * @author Jiaju Zhuang + */ +public class Validate { + + private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false"; + private static final String DEFAULT_IS_NULL_EX_MESSAGE = "The validated object is null"; + + /** + *

Validate that the argument condition is {@code true}; otherwise + * throwing an exception with the specified message. This method is useful when + * validating according to an arbitrary boolean expression, such as validating a + * primitive number or using your own custom validation expression.

+ * + *
Validate.isTrue(i > 0.0, "The value must be greater than zero: %d", i);
+ * + *

For performance reasons, the long value is passed as a separate parameter and + * appended to the exception message only in the case of an error.

+ * + * @param expression the boolean expression to check + * @param message the {@link String#format(String, Object...)} exception message if invalid, not null + * @param value the value to append to the message when invalid + * @throws IllegalArgumentException if expression is {@code false} + * @see #isTrue(boolean) + * @see #isTrue(boolean, String, double) + * @see #isTrue(boolean, String, Object...) + */ + public static void isTrue(final boolean expression, final String message, final long value) { + if (!expression) { + throw new IllegalArgumentException(String.format(message, Long.valueOf(value))); + } + } + + /** + *

Validate that the argument condition is {@code true}; otherwise + * throwing an exception with the specified message. This method is useful when + * validating according to an arbitrary boolean expression, such as validating a + * primitive number or using your own custom validation expression.

+ * + *
Validate.isTrue(d > 0.0, "The value must be greater than zero: %s", d);
+ * + *

For performance reasons, the double value is passed as a separate parameter and + * appended to the exception message only in the case of an error.

+ * + * @param expression the boolean expression to check + * @param message the {@link String#format(String, Object...)} exception message if invalid, not null + * @param value the value to append to the message when invalid + * @throws IllegalArgumentException if expression is {@code false} + * @see #isTrue(boolean) + * @see #isTrue(boolean, String, long) + * @see #isTrue(boolean, String, Object...) + */ + public static void isTrue(final boolean expression, final String message, final double value) { + if (!expression) { + throw new IllegalArgumentException(String.format(message, Double.valueOf(value))); + } + } + + /** + *

Validate that the argument condition is {@code true}; otherwise + * throwing an exception with the specified message. This method is useful when + * validating according to an arbitrary boolean expression, such as validating a + * primitive number or using your own custom validation expression.

+ * + *
+     * Validate.isTrue(i >= min && i <= max, "The value must be between %d and %d", min, max);
+     * Validate.isTrue(myObject.isOk(), "The object is not okay");
+ * + * @param expression the boolean expression to check + * @param message the {@link String#format(String, Object...)} exception message if invalid, not null + * @param values the optional values for the formatted exception message, null array not recommended + * @throws IllegalArgumentException if expression is {@code false} + * @see #isTrue(boolean) + * @see #isTrue(boolean, String, long) + * @see #isTrue(boolean, String, double) + */ + public static void isTrue(final boolean expression, final String message, final Object... values) { + if (!expression) { + throw new IllegalArgumentException(String.format(message, values)); + } + } + + /** + *

Validate that the argument condition is {@code true}; otherwise + * throwing an exception. This method is useful when validating according + * to an arbitrary boolean expression, such as validating a + * primitive number or using your own custom validation expression.

+ * + *
+     * Validate.isTrue(i > 0);
+     * Validate.isTrue(myObject.isOk());
+ * + *

The message of the exception is "The validated expression is + * false".

+ * + * @param expression the boolean expression to check + * @throws IllegalArgumentException if expression is {@code false} + * @see #isTrue(boolean, String, long) + * @see #isTrue(boolean, String, double) + * @see #isTrue(boolean, String, Object...) + */ + public static void isTrue(final boolean expression) { + if (!expression) { + throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE); + } + } + + + /** + *

Validate that the specified argument is not {@code null}; + * otherwise throwing an exception. + * + *

Validate.notNull(myObject, "The object must not be null");
+ * + *

The message of the exception is "The validated object is + * null".

+ * + * @param the object type + * @param object the object to check + * @return the validated object (never {@code null} for method chaining) + * @throws NullPointerException if the object is {@code null} + * @see #notNull(Object, String, Object...) + */ + public static T notNull(final T object) { + return notNull(object, DEFAULT_IS_NULL_EX_MESSAGE); + } + + /** + *

Validate that the specified argument is not {@code null}; + * otherwise throwing an exception with the specified message. + * + *

Validate.notNull(myObject, "The object must not be null");
+ * + * @param the object type + * @param object the object to check + * @param message the {@link String#format(String, Object...)} exception message if invalid, not null + * @param values the optional values for the formatted exception message + * @return the validated object (never {@code null} for method chaining) + * @throws NullPointerException if the object is {@code null} + * @see #notNull(Object) + */ + public static T notNull(final T object, final String message, final Object... values) { + return Objects.requireNonNull(object, () -> String.format(message, values)); + } +} diff --git a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java index 186708c9..71e1fd54 100644 --- a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java +++ b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java @@ -1,6 +1,14 @@ package com.alibaba.excel.util; import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + +import com.alibaba.excel.metadata.csv.CsvWorkbook; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.hssf.usermodel.HSSFWorkbook; @@ -13,53 +21,65 @@ import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import com.alibaba.excel.support.ExcelTypeEnum; -import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; - /** - * * @author jipengfei */ public class WorkBookUtil { - private static final int ROW_ACCESS_WINDOW_SIZE = 500; + public static final int ROW_ACCESS_WINDOW_SIZE = 500; private WorkBookUtil() {} public static void createWorkBook(WriteWorkbookHolder writeWorkbookHolder) throws IOException { - if (ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) { - if (writeWorkbookHolder.getTempTemplateInputStream() != null) { - XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream()); - writeWorkbookHolder.setCachedWorkbook(xssfWorkbook); + switch (writeWorkbookHolder.getExcelType()) { + case XLSX: + if (writeWorkbookHolder.getTempTemplateInputStream() != null) { + XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream()); + writeWorkbookHolder.setCachedWorkbook(xssfWorkbook); + if (writeWorkbookHolder.getInMemory()) { + writeWorkbookHolder.setWorkbook(xssfWorkbook); + } else { + writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE)); + } + return; + } + Workbook workbook; if (writeWorkbookHolder.getInMemory()) { - writeWorkbookHolder.setWorkbook(xssfWorkbook); + workbook = new XSSFWorkbook(); } else { - writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE)); + workbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE); } + writeWorkbookHolder.setCachedWorkbook(workbook); + writeWorkbookHolder.setWorkbook(workbook); return; - } - Workbook workbook = null; - if (writeWorkbookHolder.getInMemory()) { - workbook = new XSSFWorkbook(); - } else { - workbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE); - } - writeWorkbookHolder.setCachedWorkbook(workbook); - writeWorkbookHolder.setWorkbook(workbook); - return; - } - HSSFWorkbook hssfWorkbook; - if (writeWorkbookHolder.getTempTemplateInputStream() != null) { - hssfWorkbook = new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream())); - } else { - hssfWorkbook = new HSSFWorkbook(); - } - writeWorkbookHolder.setCachedWorkbook(hssfWorkbook); - writeWorkbookHolder.setWorkbook(hssfWorkbook); - if (writeWorkbookHolder.getPassword() != null) { - Biff8EncryptionKey.setCurrentUserPassword(writeWorkbookHolder.getPassword()); - hssfWorkbook.writeProtectWorkbook(writeWorkbookHolder.getPassword(), StringUtils.EMPTY); + case XLS: + HSSFWorkbook hssfWorkbook; + if (writeWorkbookHolder.getTempTemplateInputStream() != null) { + hssfWorkbook = new HSSFWorkbook( + new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream())); + } else { + hssfWorkbook = new HSSFWorkbook(); + } + writeWorkbookHolder.setCachedWorkbook(hssfWorkbook); + writeWorkbookHolder.setWorkbook(hssfWorkbook); + if (writeWorkbookHolder.getPassword() != null) { + Biff8EncryptionKey.setCurrentUserPassword(writeWorkbookHolder.getPassword()); + hssfWorkbook.writeProtectWorkbook(writeWorkbookHolder.getPassword(), StringUtils.EMPTY); + } + return; + case CSV: + CsvWorkbook csvWorkbook = new CsvWorkbook(new PrintWriter( + new OutputStreamWriter(writeWorkbookHolder.getOutputStream(), writeWorkbookHolder.getCharset())), + writeWorkbookHolder.getGlobalConfiguration().getLocale(), + writeWorkbookHolder.getGlobalConfiguration().getUse1904windowing(), + writeWorkbookHolder.getGlobalConfiguration().getUseScientificFormat()); + writeWorkbookHolder.setCachedWorkbook(csvWorkbook); + writeWorkbookHolder.setWorkbook(csvWorkbook); + return; + default: + throw new UnsupportedOperationException("Wrong excel type."); } + } public static Sheet createSheet(Workbook workbook, String sheetName) { @@ -91,4 +111,20 @@ public class WorkBookUtil { cell.setCellValue(cellValue); return cell; } + + public static void fillDataFormat(WriteCellData cellData, String format, String defaultFormat) { + if (cellData.getWriteCellStyle() == null) { + cellData.setWriteCellStyle(new WriteCellStyle()); + } + if (cellData.getWriteCellStyle().getDataFormatData() == null) { + cellData.getWriteCellStyle().setDataFormatData(new DataFormatData()); + } + if (cellData.getWriteCellStyle().getDataFormatData().getFormat() == null) { + if (format == null) { + cellData.getWriteCellStyle().getDataFormatData().setFormat(defaultFormat); + } else { + cellData.getWriteCellStyle().getDataFormatData().setFormat(format); + } + } + } } diff --git a/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java b/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java index 044e7b2e..2e7863e8 100644 --- a/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java +++ b/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java @@ -1,20 +1,23 @@ package com.alibaba.excel.util; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; - import com.alibaba.excel.context.WriteContext; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.handler.RowWriteHandler; import com.alibaba.excel.write.handler.SheetWriteHandler; import com.alibaba.excel.write.handler.WorkbookWriteHandler; import com.alibaba.excel.write.handler.WriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; +import com.alibaba.excel.write.handler.context.RowWriteHandlerContext; +import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext; +import com.alibaba.excel.write.handler.context.WorkbookWriteHandlerContext; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; /** * Write handler utils @@ -25,7 +28,6 @@ public class WriteHandlerUtils { private WriteHandlerUtils() {} - public static void beforeWorkbookCreate(WriteContext writeContext) { beforeWorkbookCreate(writeContext, false); } @@ -35,9 +37,10 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + WorkbookWriteHandlerContext context = new WorkbookWriteHandlerContext(writeContext, null); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof WorkbookWriteHandler) { - ((WorkbookWriteHandler) writeHandler).beforeWorkbookCreate(); + ((WorkbookWriteHandler)writeHandler).beforeWorkbookCreate(context); } } } @@ -51,9 +54,11 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + WorkbookWriteHandlerContext context = new WorkbookWriteHandlerContext(writeContext, + writeContext.writeWorkbookHolder()); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof WorkbookWriteHandler) { - ((WorkbookWriteHandler) writeHandler).afterWorkbookCreate(writeContext.writeWorkbookHolder()); + ((WorkbookWriteHandler)writeHandler).afterWorkbookCreate(context); } } } @@ -64,9 +69,11 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + WorkbookWriteHandlerContext context = new WorkbookWriteHandlerContext(writeContext, + writeContext.writeWorkbookHolder()); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof WorkbookWriteHandler) { - ((WorkbookWriteHandler) writeHandler).afterWorkbookDispose(writeContext.writeWorkbookHolder()); + ((WorkbookWriteHandler)writeHandler).afterWorkbookDispose(context); } } } @@ -80,15 +87,15 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + SheetWriteHandlerContext context = new SheetWriteHandlerContext(writeContext, + writeContext.writeWorkbookHolder(), writeContext.writeSheetHolder()); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof SheetWriteHandler) { - ((SheetWriteHandler) writeHandler).beforeSheetCreate(writeContext.writeWorkbookHolder(), - writeContext.writeSheetHolder()); + ((SheetWriteHandler)writeHandler).beforeSheetCreate(context); } } } - public static void afterSheetCreate(WriteContext writeContext) { afterSheetCreate(writeContext, false); } @@ -98,16 +105,13 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + SheetWriteHandlerContext context = new SheetWriteHandlerContext(writeContext, + writeContext.writeWorkbookHolder(), writeContext.writeSheetHolder()); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof SheetWriteHandler) { - ((SheetWriteHandler) writeHandler).afterSheetCreate(writeContext.writeWorkbookHolder(), - writeContext.writeSheetHolder()); + ((SheetWriteHandler)writeHandler).afterSheetCreate(context); } } - if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) { - writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler() - .sheet(writeContext.writeSheetHolder().getSheetNo(), writeContext.writeSheetHolder().getSheet()); - } } public static void beforeCellCreate(WriteContext writeContext, Row row, Head head, Integer columnIndex, @@ -117,10 +121,12 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), + writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row, null, columnIndex, relativeRowIndex, + head, null, isHead); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler) writeHandler).beforeCellCreate(writeContext.writeSheetHolder(), - writeContext.writeTableHolder(), row, head, columnIndex, relativeRowIndex, isHead); + ((CellWriteHandler)writeHandler).beforeCellCreate(context); } } } @@ -132,54 +138,57 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), + writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell, + cell.getColumnIndex(), relativeRowIndex, head, null, isHead); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler) writeHandler).afterCellCreate(writeContext.writeSheetHolder(), - writeContext.writeTableHolder(), cell, head, relativeRowIndex, isHead); + ((CellWriteHandler)writeHandler).afterCellCreate(context); } } } - public static void afterCellDataConverted(WriteContext writeContext, CellData cellData, Cell cell, Head head, + public static void afterCellDataConverted(WriteContext writeContext, WriteCellData cellData, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { List handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class); if (handlerList == null || handlerList.isEmpty()) { return; } + List> cellDataList = cellData == null ? null : ListUtils.newArrayList(cellData); + CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), + writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell, + cell.getColumnIndex(), relativeRowIndex, head, cellDataList, isHead); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler) writeHandler).afterCellDataConverted(writeContext.writeSheetHolder(), - writeContext.writeTableHolder(), cellData, cell, head, relativeRowIndex, isHead); + ((CellWriteHandler)writeHandler).afterCellDataConverted(context); } } } - public static void afterCellDispose(WriteContext writeContext, CellData cellData, Cell cell, Head head, + public static void afterCellDispose(WriteContext writeContext, WriteCellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { - List cellDataList = new ArrayList(); - if (cell != null) { - cellDataList.add(cellData); - } + List> cellDataList = cellData == null ? null : ListUtils.newArrayList(cellData); afterCellDispose(writeContext, cellDataList, cell, head, relativeRowIndex, isHead); } - public static void afterCellDispose(WriteContext writeContext, List cellDataList, Cell cell, Head head, + public static void afterCellDispose(WriteContext writeContext, List> cellDataList, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { List handlerList = writeContext.currentWriteHolder().writeHandlerMap().get(CellWriteHandler.class); if (handlerList == null || handlerList.isEmpty()) { return; } + CellWriteHandlerContext context = new CellWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), + writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell.getRow(), cell, + cell.getColumnIndex(), relativeRowIndex, head, cellDataList, isHead); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler) writeHandler).afterCellDispose(writeContext.writeSheetHolder(), - writeContext.writeTableHolder(), cellDataList, cell, head, relativeRowIndex, isHead); + ((CellWriteHandler)writeHandler).afterCellDispose(context); } } - if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) { - writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().cell(cell.getRowIndex(), cell); - } } public static void beforeRowCreate(WriteContext writeContext, Integer rowIndex, Integer relativeRowIndex, @@ -188,10 +197,11 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + RowWriteHandlerContext context = new RowWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), + writeContext.writeSheetHolder(), writeContext.writeTableHolder(), rowIndex, null, relativeRowIndex, isHead); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof RowWriteHandler) { - ((RowWriteHandler) writeHandler).beforeRowCreate(writeContext.writeSheetHolder(), - writeContext.writeTableHolder(), rowIndex, relativeRowIndex, isHead); + ((RowWriteHandler)writeHandler).beforeRowCreate(context); } } } @@ -201,13 +211,14 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + RowWriteHandlerContext context = new RowWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), + writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row.getRowNum(), row, relativeRowIndex, + isHead); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof RowWriteHandler) { - ((RowWriteHandler) writeHandler).afterRowCreate(writeContext.writeSheetHolder(), - writeContext.writeTableHolder(), row, relativeRowIndex, isHead); + ((RowWriteHandler)writeHandler).afterRowCreate(context); } } - } public static void afterRowDispose(WriteContext writeContext, Row row, Integer relativeRowIndex, Boolean isHead) { @@ -215,15 +226,14 @@ public class WriteHandlerUtils { if (handlerList == null || handlerList.isEmpty()) { return; } + RowWriteHandlerContext context = new RowWriteHandlerContext(writeContext, writeContext.writeWorkbookHolder(), + writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row.getRowNum(), row, relativeRowIndex, + isHead); for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof RowWriteHandler) { - ((RowWriteHandler) writeHandler).afterRowDispose(writeContext.writeSheetHolder(), - writeContext.writeTableHolder(), row, relativeRowIndex, isHead); + ((RowWriteHandler)writeHandler).afterRowDispose(context); } } - if (null != writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler()) { - writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row); - } } private static List getHandlerList(WriteContext writeContext, Class clazz, diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java index d3a50e35..a9f7e601 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java @@ -1,5 +1,6 @@ package com.alibaba.excel.write; +import java.util.Collection; import java.util.List; import com.alibaba.excel.context.WriteContext; @@ -20,10 +21,10 @@ public interface ExcelBuilder { * java basic type or java model extend BaseModel * @param writeSheet * Write the sheet - * @deprecated please use{@link ExcelBuilder#addContent(List, WriteSheet, WriteTable)} + * @deprecated please use{@link ExcelBuilder#addContent(Collection, WriteSheet, WriteTable)} */ @Deprecated - void addContent(List data, WriteSheet writeSheet); + void addContent(Collection data, WriteSheet writeSheet); /** * WorkBook increase value @@ -35,7 +36,7 @@ public interface ExcelBuilder { * @param writeTable * Write the table */ - void addContent(List data, WriteSheet writeSheet, WriteTable writeTable); + void addContent(Collection data, WriteSheet writeSheet, WriteTable writeTable); /** * WorkBook fill value diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index 0c7158ed..d6503c6c 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -1,13 +1,12 @@ package com.alibaba.excel.write; -import java.util.List; - -import org.apache.poi.ss.util.CellRangeAddress; +import java.util.Collection; import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContextImpl; import com.alibaba.excel.enums.WriteTypeEnum; import com.alibaba.excel.exception.ExcelGenerateException; +import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.write.executor.ExcelWriteAddExecutor; import com.alibaba.excel.write.executor.ExcelWriteFillExecutor; @@ -16,6 +15,8 @@ import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteWorkbook; import com.alibaba.excel.write.metadata.fill.FillConfig; +import org.apache.poi.ss.util.CellRangeAddress; + /** * @author jipengfei */ @@ -43,12 +44,12 @@ public class ExcelBuilderImpl implements ExcelBuilder { } @Override - public void addContent(List data, WriteSheet writeSheet) { + public void addContent(Collection data, WriteSheet writeSheet) { addContent(data, writeSheet, null); } @Override - public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) { + public void addContent(Collection data, WriteSheet writeSheet, WriteTable writeTable) { try { context.currentSheet(writeSheet, WriteTypeEnum.ADD); context.currentTable(writeTable); @@ -71,6 +72,9 @@ public class ExcelBuilderImpl implements ExcelBuilder { if (context.writeWorkbookHolder().getTempTemplateInputStream() == null) { throw new ExcelGenerateException("Calling the 'fill' method must use a template."); } + if (context.writeWorkbookHolder().getExcelType() == ExcelTypeEnum.CSV) { + throw new ExcelGenerateException("csv does not support filling data."); + } context.currentSheet(writeSheet, WriteTypeEnum.FILL); if (excelWriteFillExecutor == null) { excelWriteFillExecutor = new ExcelWriteFillExecutor(context); diff --git a/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java b/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java index d44c0ad0..751ae5cd 100644 --- a/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/AbstractExcelWriterParameterBuilder.java @@ -81,7 +81,7 @@ public abstract class AbstractExcelWriterParameterBuilder excludeColumnFiledNames) { - parameter().setExcludeColumnFiledNames(excludeColumnFiledNames); + parameter().setExcludeColumnFieldNames(excludeColumnFiledNames); return self(); } @@ -97,7 +97,7 @@ public abstract class AbstractExcelWriterParameterBuilder includeColumnFiledNames) { - parameter().setIncludeColumnFiledNames(includeColumnFiledNames); + parameter().setIncludeColumnFieldNames(includeColumnFiledNames); return self(); } diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java index 12c2f22f..dcd0a80d 100644 --- a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java @@ -6,7 +6,6 @@ import java.io.OutputStream; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.support.ExcelTypeEnum; -import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.metadata.WriteWorkbook; /** @@ -18,7 +17,7 @@ public class ExcelWriterBuilder extends AbstractExcelWriterParameterBuilder * Comment and RichTextString are only supported in memory mode. */ @@ -66,21 +65,6 @@ public class ExcelWriterBuilder extends AbstractExcelWriterParameterBuilder - * Default true - * - * @param convertAllFiled - * @return - * @deprecated Just to be compatible with historical data, The default is always going to be convert all filed. - */ - @Deprecated - public ExcelWriterBuilder convertAllFiled(Boolean convertAllFiled) { - writeWorkbook.setConvertAllFiled(convertAllFiled); - return this; - } public ExcelWriterBuilder excelType(ExcelTypeEnum excelType) { writeWorkbook.setExcelType(excelType); @@ -115,16 +99,6 @@ public class ExcelWriterBuilder extends AbstractExcelWriterParameterBuilder data) { if (excelWriter == null) { throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method"); } @@ -74,6 +75,18 @@ public class ExcelWriterSheetBuilder extends AbstractExcelWriterParameterBuilder excelWriter.finish(); } + public void doWrite(Supplier> supplier) { + doWrite(supplier.get()); + } + + public void doFill(Supplier supplier) { + doFill(supplier.get()); + } + + public void doFill(Supplier supplier, FillConfig fillConfig) { + doFill(supplier.get(), fillConfig); + } + public ExcelWriterTableBuilder table() { return table(null); } diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterTableBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterTableBuilder.java index 077361ad..279ac30a 100644 --- a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterTableBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterTableBuilder.java @@ -1,6 +1,7 @@ package com.alibaba.excel.write.builder; -import java.util.List; +import java.util.Collection; +import java.util.function.Supplier; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.exception.ExcelGenerateException; @@ -47,7 +48,7 @@ public class ExcelWriterTableBuilder extends AbstractExcelWriterParameterBuilder return writeTable; } - public void doWrite(List data) { + public void doWrite(Collection data) { if (excelWriter == null) { throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet().table()' to call this method"); } @@ -55,6 +56,10 @@ public class ExcelWriterTableBuilder extends AbstractExcelWriterParameterBuilder excelWriter.finish(); } + public void doWrite(Supplier> supplier) { + doWrite(supplier.get()); + } + @Override protected WriteTable parameter() { return writeTable; diff --git a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java index 4eb115c5..5cd0cda2 100644 --- a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java @@ -1,22 +1,41 @@ package com.alibaba.excel.write.executor; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.CreationHelper; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.Sheet; +import java.util.List; import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; +import com.alibaba.excel.converters.NullableObjectConverter; +import com.alibaba.excel.converters.WriteConverterContext; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.exception.ExcelDataConvertException; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.CommentData; +import com.alibaba.excel.metadata.data.FormulaData; +import com.alibaba.excel.metadata.data.HyperlinkData; +import com.alibaba.excel.metadata.data.ImageData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.util.DateUtils; +import com.alibaba.excel.util.FileTypeUtils; +import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.util.WriteHandlerUtils; import com.alibaba.excel.write.metadata.holder.WriteHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.hssf.usermodel.HSSFClientAnchor; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; /** * Excel write Executor @@ -30,22 +49,39 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { this.writeContext = writeContext; } - protected CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, - ExcelContentProperty excelContentProperty, Head head, Integer relativeRowIndex) { - if (value == null) { - return new CellData(CellDataTypeEnum.EMPTY); - } - if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) { + protected WriteCellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, + CellDataTypeEnum targetType, Cell cell, Object value, ExcelContentProperty excelContentProperty, Head head, + Integer relativeRowIndex) { + boolean needTrim = value != null && (value instanceof String && currentWriteHolder.globalConfiguration() + .getAutoTrim()); + if (needTrim) { value = ((String)value).trim(); } - CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty); - if (cellData.getFormula() != null && cellData.getFormula()) { - cell.setCellFormula(cellData.getFormulaValue()); - } + WriteCellData cellData = convert(currentWriteHolder, clazz, targetType, cell, value, excelContentProperty); + WriteHandlerUtils.afterCellDataConverted(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); + + // Fill in picture information + fillImage(cell, cellData.getImageDataList()); + + // Fill in comment information + fillComment(cell, cellData.getCommentData()); + + // Fill in hyper link information + fillHyperLink(cell, cellData.getHyperlinkData()); + + // Fill in formula information + fillFormula(cell, cellData.getFormulaData()); + + // Fill in style information + fillStyle(cell, cellData.getWriteCellStyle()); + + // Fill index + cellData.setRowIndex(cell.getRowIndex()); + cellData.setColumnIndex(cell.getColumnIndex()); + if (cellData.getType() == null) { cellData.setType(CellDataTypeEnum.EMPTY); } - WriteHandlerUtils.afterCellDataConverted(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); switch (cellData.getType()) { case STRING: cell.setCellValue(cellData.getStringValue()); @@ -56,27 +92,154 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { case NUMBER: cell.setCellValue(cellData.getNumberValue().doubleValue()); return cellData; - case IMAGE: - setImageValue(cellData, cell); + case DATE: + cell.setCellValue(cellData.getDateValue()); + return cellData; + case RICH_TEXT_STRING: + cell.setCellValue(StyleUtil + .buildRichTextString(writeContext.writeWorkbookHolder(), cellData.getRichTextStringDataValue())); return cellData; case EMPTY: return cellData; default: throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), cellData, excelContentProperty, "Not supported data:" + value + " return type:" + cell.getCellType() - + "at row:" + cell.getRow().getRowNum()); + + "at row:" + cell.getRow().getRowNum()); + } + + } + + private void fillStyle(Cell cell, WriteCellStyle writeCellStyle) { + if (writeCellStyle == null) { + return; + } + CellStyle cellStyle = writeContext.writeWorkbookHolder().createCellStyle(writeCellStyle); + cell.setCellStyle(cellStyle); + } + + private void fillFormula(Cell cell, FormulaData formulaData) { + if (formulaData == null) { + return; + } + if (formulaData.getFormulaValue() != null) { + cell.setCellFormula(formulaData.getFormulaValue()); + } + } + + private void fillHyperLink(Cell cell, HyperlinkData hyperlinkData) { + if (hyperlinkData == null) { + return; + } + CreationHelper helper = cell.getSheet().getWorkbook().getCreationHelper(); + Hyperlink hyperlink = helper.createHyperlink(StyleUtil.getHyperlinkType(hyperlinkData.getHyperlinkType())); + hyperlink.setAddress(hyperlinkData.getAddress()); + hyperlink.setFirstRow(StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), hyperlinkData.getFirstRowIndex(), + hyperlinkData.getRelativeFirstRowIndex())); + hyperlink.setFirstColumn(StyleUtil.getCellCoordinate(cell.getColumnIndex(), hyperlinkData.getFirstColumnIndex(), + hyperlinkData.getRelativeFirstColumnIndex())); + hyperlink.setLastRow(StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), hyperlinkData.getLastRowIndex(), + hyperlinkData.getRelativeLastRowIndex())); + hyperlink.setLastColumn(StyleUtil.getCellCoordinate(cell.getColumnIndex(), hyperlinkData.getLastColumnIndex(), + hyperlinkData.getRelativeLastColumnIndex())); + cell.setHyperlink(hyperlink); + } + + private void fillComment(Cell cell, CommentData commentData) { + if (commentData == null) { + return; + } + ClientAnchor anchor; + if (writeContext.writeWorkbookHolder().getExcelType() == ExcelTypeEnum.XLSX) { + anchor = new XSSFClientAnchor(StyleUtil.getCoordinate(commentData.getLeft()), + StyleUtil.getCoordinate(commentData.getTop()), + StyleUtil.getCoordinate(commentData.getRight()), + StyleUtil.getCoordinate(commentData.getBottom()), + StyleUtil.getCellCoordinate(cell.getColumnIndex(), commentData.getFirstColumnIndex(), + commentData.getRelativeFirstColumnIndex()), + StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), commentData.getFirstRowIndex(), + commentData.getRelativeFirstRowIndex()), + StyleUtil.getCellCoordinate(cell.getColumnIndex(), commentData.getLastColumnIndex(), + commentData.getRelativeLastColumnIndex()) + 1, + StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), commentData.getLastRowIndex(), + commentData.getRelativeLastRowIndex()) + 1); + } else { + anchor = new HSSFClientAnchor(StyleUtil.getCoordinate(commentData.getLeft()), + StyleUtil.getCoordinate(commentData.getTop()), + StyleUtil.getCoordinate(commentData.getRight()), + StyleUtil.getCoordinate(commentData.getBottom()), + (short)StyleUtil.getCellCoordinate(cell.getColumnIndex(), commentData.getFirstColumnIndex(), + commentData.getRelativeFirstColumnIndex()), + StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), commentData.getFirstRowIndex(), + commentData.getRelativeFirstRowIndex()), + (short)(StyleUtil.getCellCoordinate(cell.getColumnIndex(), commentData.getLastColumnIndex(), + commentData.getRelativeLastColumnIndex()) + 1), + StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), commentData.getLastRowIndex(), + commentData.getRelativeLastRowIndex()) + 1); } + Comment comment = cell.getSheet().createDrawingPatriarch().createCellComment(anchor); + if (commentData.getRichTextStringData() != null) { + comment.setString( + StyleUtil.buildRichTextString(writeContext.writeWorkbookHolder(), commentData.getRichTextStringData())); + } + if (commentData.getAuthor() != null) { + comment.setAuthor(commentData.getAuthor()); + } + cell.setCellComment(comment); } - protected CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, - ExcelContentProperty excelContentProperty) { - if (value == null) { - return new CellData(CellDataTypeEnum.EMPTY); + protected void fillImage(Cell cell, List imageDataList) { + if (CollectionUtils.isEmpty(imageDataList)) { + return; + } + Sheet sheet = cell.getSheet(); + Drawing drawing = sheet.getDrawingPatriarch(); + if (drawing == null) { + drawing = sheet.createDrawingPatriarch(); } + CreationHelper helper = sheet.getWorkbook().getCreationHelper(); + for (ImageData imageData : imageDataList) { + int index = sheet.getWorkbook().addPicture(imageData.getImage(), + FileTypeUtils.getImageTypeFormat(imageData.getImage())); + ClientAnchor anchor = helper.createClientAnchor(); + if (imageData.getTop() != null) { + anchor.setDy1(StyleUtil.getCoordinate(imageData.getTop())); + } + if (imageData.getRight() != null) { + anchor.setDx2(-StyleUtil.getCoordinate(imageData.getRight())); + } + if (imageData.getBottom() != null) { + anchor.setDy2(-StyleUtil.getCoordinate(imageData.getBottom())); + } + if (imageData.getLeft() != null) { + anchor.setDx1(StyleUtil.getCoordinate(imageData.getLeft())); + } + anchor.setRow1(StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), imageData.getFirstRowIndex(), + imageData.getRelativeFirstRowIndex())); + anchor.setCol1(StyleUtil.getCellCoordinate(cell.getColumnIndex(), imageData.getFirstColumnIndex(), + imageData.getRelativeFirstColumnIndex())); + anchor.setRow2(StyleUtil.getCellCoordinate(cell.getRow().getRowNum(), imageData.getLastRowIndex(), + imageData.getRelativeLastRowIndex()) + 1); + anchor.setCol2(StyleUtil.getCellCoordinate(cell.getColumnIndex(), imageData.getLastColumnIndex(), + imageData.getRelativeLastColumnIndex()) + 1); + if (imageData.getAnchorType() != null) { + anchor.setAnchorType(imageData.getAnchorType().getValue()); + } + drawing.createPicture(anchor, index); + } + } + + protected WriteCellData convert(WriteHolder currentWriteHolder, Class clazz, CellDataTypeEnum targetType, + Cell cell, Object value, ExcelContentProperty excelContentProperty) { // This means that the user has defined the data. - if (value instanceof CellData) { - CellData cellDataValue = (CellData)value; + if (clazz == WriteCellData.class) { + if (value == null) { + return new WriteCellData<>(CellDataTypeEnum.EMPTY); + } + WriteCellData cellDataValue = (WriteCellData)value; if (cellDataValue.getType() != null) { + // Configuration information may not be read here + fillProperty(cellDataValue, excelContentProperty); + return cellDataValue; } else { if (cellDataValue.getData() == null) { @@ -84,67 +247,86 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { return cellDataValue; } } - CellData cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), cell, - cellDataValue.getData(), excelContentProperty); + WriteCellData cellDataReturn = doConvert(currentWriteHolder, cellDataValue.getData().getClass(), + targetType, cell, cellDataValue.getData(), excelContentProperty); + + if (cellDataValue.getImageDataList() != null) { + cellDataReturn.setImageDataList(cellDataValue.getImageDataList()); + } + if (cellDataValue.getCommentData() != null) { + cellDataReturn.setCommentData(cellDataValue.getCommentData()); + } + if (cellDataValue.getHyperlinkData() != null) { + cellDataReturn.setHyperlinkData(cellDataValue.getHyperlinkData()); + } // The formula information is subject to user input - if (cellDataValue.getFormula() != null) { - cellDataReturn.setFormula(cellDataValue.getFormula()); - cellDataReturn.setFormulaValue(cellDataValue.getFormulaValue()); + if (cellDataValue.getFormulaData() != null) { + cellDataReturn.setFormulaData(cellDataValue.getFormulaData()); + } + if (cellDataValue.getWriteCellStyle() != null) { + cellDataReturn.setWriteCellStyle(cellDataValue.getWriteCellStyle()); } return cellDataReturn; } - return doConvert(currentWriteHolder, clazz, cell, value, excelContentProperty); + return doConvert(currentWriteHolder, clazz, targetType, cell, value, excelContentProperty); + } + + private void fillProperty(WriteCellData cellDataValue, ExcelContentProperty excelContentProperty) { + switch (cellDataValue.getType()) { + case DATE: + String dateFormat = null; + if (excelContentProperty != null && excelContentProperty.getDateTimeFormatProperty() != null) { + dateFormat = excelContentProperty.getDateTimeFormatProperty().getFormat(); + } + WorkBookUtil.fillDataFormat(cellDataValue, dateFormat, DateUtils.defaultDateFormat); + return; + case NUMBER: + String numberFormat = null; + if (excelContentProperty != null && excelContentProperty.getNumberFormatProperty() != null) { + numberFormat = excelContentProperty.getNumberFormatProperty().getFormat(); + } + WorkBookUtil.fillDataFormat(cellDataValue, numberFormat, null); + return; + default: + return; + } } - private CellData doConvert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, - ExcelContentProperty excelContentProperty) { - Converter converter = null; + private WriteCellData doConvert(WriteHolder currentWriteHolder, Class clazz, CellDataTypeEnum targetType, + Cell cell, Object value, ExcelContentProperty excelContentProperty) { + Converter converter = null; if (excelContentProperty != null) { converter = excelContentProperty.getConverter(); } if (converter == null) { - converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz)); + // csv is converted to string by default + if (writeContext.writeWorkbookHolder().getExcelType() == ExcelTypeEnum.CSV) { + targetType = CellDataTypeEnum.STRING; + } + converter = currentWriteHolder.converterMap().get(ConverterKeyBuild.buildKey(clazz, targetType)); + } + if (value == null && !(converter instanceof NullableObjectConverter)) { + return new WriteCellData<>(CellDataTypeEnum.EMPTY); } if (converter == null) { throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), - new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, + new WriteCellData<>(CellDataTypeEnum.EMPTY), excelContentProperty, "Can not find 'Converter' support class " + clazz.getSimpleName() + "."); } - CellData cellData; + WriteCellData cellData; try { - cellData = - converter.convertToExcelData(value, excelContentProperty, currentWriteHolder.globalConfiguration()); + cellData = ((Converter)converter).convertToExcelData( + new WriteConverterContext<>(value, excelContentProperty, writeContext)); } catch (Exception e) { throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), - new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, - "Convert data:" + value + " error,at row:" + cell.getRow().getRowNum(), e); + new WriteCellData<>(CellDataTypeEnum.EMPTY), excelContentProperty, + "Convert data:" + value + " error, at row:" + cell.getRow().getRowNum(), e); } if (cellData == null || cellData.getType() == null) { throw new ExcelDataConvertException(cell.getRow().getRowNum(), cell.getColumnIndex(), - new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, - "Convert data:" + value + " return null,at row:" + cell.getRow().getRowNum()); + new WriteCellData<>(CellDataTypeEnum.EMPTY), excelContentProperty, + "Convert data:" + value + " return null, at row:" + cell.getRow().getRowNum()); } return cellData; } - - private void setImageValue(CellData cellData, Cell cell) { - Sheet sheet = cell.getSheet(); - int index = sheet.getWorkbook().addPicture(cellData.getImageValue(), HSSFWorkbook.PICTURE_TYPE_PNG); - Drawing drawing = sheet.getDrawingPatriarch(); - if (drawing == null) { - drawing = sheet.createDrawingPatriarch(); - } - CreationHelper helper = sheet.getWorkbook().getCreationHelper(); - ClientAnchor anchor = helper.createClientAnchor(); - anchor.setDx1(0); - anchor.setDx2(0); - anchor.setDy1(0); - anchor.setDy2(0); - anchor.setCol1(cell.getColumnIndex()); - anchor.setCol2(cell.getColumnIndex() + 1); - anchor.setRow1(cell.getRowIndex()); - anchor.setRow2(cell.getRowIndex() + 1); - anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE); - drawing.createPicture(anchor, index); - } } diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java index 9f229029..e053d81f 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java @@ -2,31 +2,32 @@ package com.alibaba.excel.write.executor; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; - import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.enums.HeadKindEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.alibaba.excel.util.BeanMapUtils; import com.alibaba.excel.util.ClassUtils; -import com.alibaba.excel.util.CollectionUtils; +import com.alibaba.excel.util.FieldUtils; import com.alibaba.excel.util.WorkBookUtil; import com.alibaba.excel.util.WriteHandlerUtils; -import com.alibaba.excel.write.metadata.WriteWorkbook; -import com.alibaba.excel.write.metadata.holder.AbstractWriteHolder; +import com.alibaba.excel.write.metadata.CollectionRowData; +import com.alibaba.excel.write.metadata.MapRowData; +import com.alibaba.excel.write.metadata.RowData; import com.alibaba.excel.write.metadata.holder.WriteHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import net.sf.cglib.beans.BeanMap; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; /** * Add the data into excel @@ -39,21 +40,21 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { super(writeContext); } - public void add(List data) { + public void add(Collection data) { if (CollectionUtils.isEmpty(data)) { - data = new ArrayList(); + data = new ArrayList<>(); } WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite(); if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) { newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex(); } - // BeanMap is out of order,so use sortedAllFiledMap - Map sortedAllFiledMap = new TreeMap(); + // BeanMap is out of order, so use sortedAllFiledMap + Map sortedAllFiledMap = new TreeMap<>(); int relativeRowIndex = 0; for (Object oneRowData : data) { - int n = relativeRowIndex + newRowIndex; - addOneRowOfDataToExcel(oneRowData, n, relativeRowIndex, sortedAllFiledMap); + int lastRowIndex = relativeRowIndex + newRowIndex; + addOneRowOfDataToExcel(oneRowData, lastRowIndex, relativeRowIndex, sortedAllFiledMap); relativeRowIndex++; } } @@ -66,68 +67,73 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { WriteHandlerUtils.beforeRowCreate(writeContext, n, relativeRowIndex, Boolean.FALSE); Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n); WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE); - if (oneRowData instanceof List) { - addBasicTypeToExcel((List) oneRowData, row, relativeRowIndex); + + if (oneRowData instanceof Collection) { + addBasicTypeToExcel(new CollectionRowData((Collection)oneRowData), row, relativeRowIndex); + } else if (oneRowData instanceof Map) { + addBasicTypeToExcel(new MapRowData((Map)oneRowData), row, relativeRowIndex); } else { addJavaObjectToExcel(oneRowData, row, relativeRowIndex, sortedAllFiledMap); } WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE); } - private void addBasicTypeToExcel(List oneRowData, Row row, int relativeRowIndex) { - if (CollectionUtils.isEmpty(oneRowData)) { + private void addBasicTypeToExcel(RowData oneRowData, Row row, int relativeRowIndex) { + if (oneRowData.isEmpty()) { return; } Map headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); int dataIndex = 0; - int cellIndex = 0; + int maxCellIndex = -1; for (Map.Entry entry : headMap.entrySet()) { if (dataIndex >= oneRowData.size()) { return; } - cellIndex = entry.getKey(); + int cellIndex = entry.getKey(); Head head = entry.getValue(); doAddBasicTypeToExcel(oneRowData, head, row, relativeRowIndex, dataIndex++, cellIndex); + maxCellIndex = Math.max(maxCellIndex, cellIndex); } // Finish if (dataIndex >= oneRowData.size()) { return; } - if (cellIndex != 0) { - cellIndex++; - } + // fix https://github.com/alibaba/easyexcel/issues/1702 + // If there is data, it is written to the next cell + maxCellIndex++; + int size = oneRowData.size() - dataIndex; for (int i = 0; i < size; i++) { - doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, cellIndex++); + doAddBasicTypeToExcel(oneRowData, null, row, relativeRowIndex, dataIndex++, maxCellIndex++); } } - private void doAddBasicTypeToExcel(List oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex, + private void doAddBasicTypeToExcel(RowData oneRowData, Head head, Row row, int relativeRowIndex, int dataIndex, int cellIndex) { WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE); Cell cell = WorkBookUtil.createCell(row, cellIndex); WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE); Object value = oneRowData.get(dataIndex); - CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(), - cell, value, null, head, relativeRowIndex); + WriteCellData cellData = converterAndSet(writeContext.currentWriteHolder(), + FieldUtils.getFieldClass(oneRowData, dataIndex), null, cell, value, null, head, relativeRowIndex); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); } private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex, Map sortedAllFiledMap) { WriteHolder currentWriteHolder = writeContext.currentWriteHolder(); - BeanMap beanMap = BeanMap.create(oneRowData); + BeanMap beanMap = BeanMapUtils.create(oneRowData); Set beanMapHandledSet = new HashSet(); - int cellIndex = 0; + int maxCellIndex = -1; // If it's a class it needs to be cast by type if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) { Map headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); Map contentPropertyMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap(); for (Map.Entry entry : contentPropertyMap.entrySet()) { - cellIndex = entry.getKey(); + int cellIndex = entry.getKey(); ExcelContentProperty excelContentProperty = entry.getValue(); - String name = excelContentProperty.getField().getName(); + String name = FieldUtils.resolveCglibFieldName(excelContentProperty.getField()); if (!beanMap.containsKey(name)) { continue; } @@ -136,20 +142,23 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { Cell cell = WorkBookUtil.createCell(row, cellIndex); WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE); Object value = beanMap.get(name); - CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell, - value, excelContentProperty, head, relativeRowIndex); + WriteCellData cellData = converterAndSet(currentWriteHolder, + excelContentProperty.getField().getType(), + null, cell, value, excelContentProperty, head, relativeRowIndex); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); beanMapHandledSet.add(name); + maxCellIndex = Math.max(maxCellIndex, cellIndex); } } // Finish if (beanMapHandledSet.size() == beanMap.size()) { return; } + maxCellIndex++; + Map ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap(); initSortedAllFiledMapFieldList(oneRowData.getClass(), sortedAllFiledMap); for (Map.Entry entry : sortedAllFiledMap.entrySet()) { - cellIndex = entry.getKey(); Field field = entry.getValue(); String filedName = field.getName(); boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName) @@ -158,27 +167,29 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor { continue; } Object value = beanMap.get(filedName); - WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE); - Cell cell = WorkBookUtil.createCell(row, cellIndex); + WriteHandlerUtils.beforeCellCreate(writeContext, row, null, maxCellIndex, relativeRowIndex, Boolean.FALSE); + // fix https://github.com/alibaba/easyexcel/issues/1870 + // If there is data, it is written to the next cell + Cell cell = WorkBookUtil.createCell(row, maxCellIndex++); WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE); - CellData cellData = converterAndSet(currentWriteHolder, value == null ? null : value.getClass(), cell, - value, null, null, relativeRowIndex); + WriteCellData cellData = converterAndSet(currentWriteHolder, + FieldUtils.getFieldClass(beanMap, filedName), null, cell, value, null, null, relativeRowIndex); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE); } } - private void initSortedAllFiledMapFieldList(Class clazz, Map sortedAllFiledMap) { + private void initSortedAllFiledMapFieldList(Class clazz, Map sortedAllFiledMap) { if (!sortedAllFiledMap.isEmpty()) { return; } - WriteWorkbookHolder writeWorkbookHolder = writeContext.writeWorkbookHolder(); + + WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); boolean needIgnore = - !CollectionUtils.isEmpty(writeWorkbookHolder.getExcludeColumnFiledNames()) || !CollectionUtils - .isEmpty(writeWorkbookHolder.getExcludeColumnIndexes()) || !CollectionUtils - .isEmpty(writeWorkbookHolder.getIncludeColumnFiledNames()) || !CollectionUtils - .isEmpty(writeWorkbookHolder.getIncludeColumnIndexes()); - ClassUtils.declaredFields(clazz, sortedAllFiledMap, - writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled(), needIgnore, writeWorkbookHolder); + !CollectionUtils.isEmpty(writeSheetHolder.getExcludeColumnFieldNames()) || !CollectionUtils + .isEmpty(writeSheetHolder.getExcludeColumnIndexes()) || !CollectionUtils + .isEmpty(writeSheetHolder.getIncludeColumnFieldNames()) || !CollectionUtils + .isEmpty(writeSheetHolder.getIncludeColumnIndexes()); + ClassUtils.declaredFields(clazz, sortedAllFiledMap, needIgnore, writeSheetHolder); } } diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java index 5930a311..e91e2834 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -9,20 +9,17 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; - import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.WriteDirectionEnum; import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum; import com.alibaba.excel.exception.ExcelGenerateException; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; -import com.alibaba.excel.util.CollectionUtils; +import com.alibaba.excel.util.BeanMapUtils; +import com.alibaba.excel.util.FieldUtils; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.excel.util.MapUtils; import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.util.WriteHandlerUtils; import com.alibaba.excel.write.metadata.fill.AnalysisCell; @@ -30,7 +27,13 @@ import com.alibaba.excel.write.metadata.fill.FillConfig; import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import net.sf.cglib.beans.BeanMap; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.hssf.usermodel.PoiUtils; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; /** * Fill the data into excel @@ -48,32 +51,25 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { /** * Fields to replace in the template */ - private final Map> templateAnalysisCache = new HashMap>(8); + private final Map> templateAnalysisCache = MapUtils.newHashMap(); /** * Collection fields to replace in the template */ - private final Map> templateCollectionAnalysisCache = - new HashMap>(8); + private final Map> templateCollectionAnalysisCache = MapUtils.newHashMap(); /** * Style cache for collection fields */ - private final Map> collectionFieldStyleCache = - new HashMap>(8); + private final Map> collectionFieldStyleCache = MapUtils.newHashMap(); /** * Row height cache for collection */ - private final Map collectionRowHeightCache = new HashMap(8); + private final Map collectionRowHeightCache = MapUtils.newHashMap(); /** * Last index cache for collection fields */ - private final Map> collectionLastIndexCache = - new HashMap>(8); + private final Map> collectionLastIndexCache = MapUtils.newHashMap(); - private final Map relativeRowIndexMap = new HashMap(8); - /** - * The data prefix that is populated this time - */ - private String currentDataPrefix; + private final Map relativeRowIndexMap = MapUtils.newHashMap(); /** * The unique data encoding for this fill */ @@ -88,13 +84,16 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { data = new HashMap(16); } if (fillConfig == null) { - fillConfig = FillConfig.builder().build(true); + fillConfig = FillConfig.builder().build(); } fillConfig.init(); Object realData; + // The data prefix that is populated this time + String currentDataPrefix; + if (data instanceof FillWrapper) { - FillWrapper fillWrapper = (FillWrapper) data; + FillWrapper fillWrapper = (FillWrapper)data; currentDataPrefix = fillWrapper.getName(); realData = fillWrapper.getCollectionData(); } else { @@ -106,11 +105,11 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { // processing data if (realData instanceof Collection) { List analysisCellList = readTemplateData(templateCollectionAnalysisCache); - Collection collectionData = (Collection) realData; + Collection collectionData = (Collection)realData; if (CollectionUtils.isEmpty(collectionData)) { return; } - Iterator iterator = collectionData.iterator(); + Iterator iterator = collectionData.iterator(); if (WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection()) && fillConfig.getForceNewRow()) { shiftRows(collectionData.size(), analysisCellList); } @@ -179,15 +178,19 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { private void doFill(List analysisCellList, Object oneRowData, FillConfig fillConfig, Integer relativeRowIndex) { - Map dataMap; + if (CollectionUtils.isEmpty(analysisCellList) || oneRowData == null) { + return; + } + Map dataMap; if (oneRowData instanceof Map) { - dataMap = (Map) oneRowData; + dataMap = (Map)oneRowData; } else { - dataMap = BeanMap.create(oneRowData); + dataMap = BeanMapUtils.create(oneRowData); } WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); Map fieldNameContentPropertyMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getFieldNameContentPropertyMap(); + for (AnalysisCell analysisCell : analysisCellList) { Cell cell = getOneCell(analysisCell, fillConfig); if (analysisCell.getOnlyOneVariable()) { @@ -196,21 +199,22 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { continue; } Object value = dataMap.get(variable); - CellData cellData = converterAndSet(writeSheetHolder, value == null ? null : value.getClass(), cell, - value, fieldNameContentPropertyMap.get(variable), null, relativeRowIndex); + WriteCellData cellData = converterAndSet(writeSheetHolder, + FieldUtils.getFieldClass(dataMap, variable), + null, cell, value, fieldNameContentPropertyMap.get(variable), null, relativeRowIndex); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE); } else { StringBuilder cellValueBuild = new StringBuilder(); int index = 0; - List cellDataList = new ArrayList(); + List> cellDataList = new ArrayList<>(); for (String variable : analysisCell.getVariableList()) { cellValueBuild.append(analysisCell.getPrepareDataList().get(index++)); if (!dataMap.containsKey(variable)) { continue; } Object value = dataMap.get(variable); - CellData cellData = convert(writeSheetHolder, value == null ? null : value.getClass(), cell, value, - fieldNameContentPropertyMap.get(variable)); + WriteCellData cellData = convert(writeSheetHolder, value == null ? null : value.getClass(), + CellDataTypeEnum.STRING, cell, value, fieldNameContentPropertyMap.get(variable)); cellDataList.add(cellData); CellDataTypeEnum type = cellData.getType(); if (type != null) { @@ -255,11 +259,9 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { } Sheet sheet = writeContext.writeSheetHolder().getSheet(); - Map collectionLastIndexMap = collectionLastIndexCache.get(currentUniqueDataFlag); - if (collectionLastIndexMap == null) { - collectionLastIndexMap = new HashMap(16); - collectionLastIndexCache.put(currentUniqueDataFlag, collectionLastIndexMap); - } + Map collectionLastIndexMap = collectionLastIndexCache + .computeIfAbsent(currentUniqueDataFlag, key -> MapUtils.newHashMap()); + boolean isOriginalCell = false; Integer lastRowIndex; Integer lastColumnIndex; @@ -291,19 +293,19 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { } Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell); - Cell cell = createCellIfNecessary(row,lastColumnIndex); + Cell cell = createCellIfNecessary(row, lastColumnIndex); + + Map collectionFieldStyleMap = collectionFieldStyleCache.computeIfAbsent( + currentUniqueDataFlag, key -> MapUtils.newHashMap()); - Map collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag); - if (collectionFieldStyleMap == null) { - collectionFieldStyleMap = new HashMap(16); - collectionFieldStyleCache.put(currentUniqueDataFlag, collectionFieldStyleMap); - } if (isOriginalCell) { collectionFieldStyleMap.put(analysisCell, cell.getCellStyle()); } else { - CellStyle cellStyle = collectionFieldStyleMap.get(analysisCell); - if (cellStyle != null) { - cell.setCellStyle(cellStyle); + if (fillConfig.getAutoStyle()) { + CellStyle cellStyle = collectionFieldStyleMap.get(analysisCell); + if (cellStyle != null) { + cell.setCellStyle(cellStyle); + } } } return cell; @@ -324,6 +326,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { AnalysisCell analysisCell, boolean isOriginalCell) { Row row = sheet.getRow(lastRowIndex); if (row != null) { + checkRowHeight(analysisCell, fillConfig, isOriginalCell, row); return row; } row = cachedSheet.getRow(lastRowIndex); @@ -333,7 +336,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { row = cachedSheet.createRow(lastRowIndex); } else { // The last row of the middle disk inside empty rows, resulting in cachedSheet can not get inside. - // Will throw Attempting to write a row[" + rownum + "] " + "in the range [0," + this._sh.getLastRowNum() + "] that is already written to disk. + // Will throw Attempting to write a row[" + rownum + "] " + "in the range [0," + this._sh + // .getLastRowNum() + "] that is already written to disk. try { row = sheet.createRow(lastRowIndex); } catch (IllegalArgumentException ignore) { @@ -352,13 +356,16 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { if (!analysisCell.getFirstRow() || !WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection())) { return; } - if (isOriginalCell) { + // fix https://github.com/alibaba/easyexcel/issues/1869 + if (isOriginalCell && PoiUtils.customHeight(row)) { collectionRowHeightCache.put(currentUniqueDataFlag, row.getHeight()); return; } - Short rowHeight = collectionRowHeightCache.get(currentUniqueDataFlag); - if (rowHeight != null) { - row.setHeight(rowHeight); + if (fillConfig.getAutoStyle()) { + Short rowHeight = collectionRowHeightCache.get(currentUniqueDataFlag); + if (rowHeight != null) { + row.setHeight(rowHeight); + } } } @@ -368,7 +375,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { return analysisCellList; } Sheet sheet = writeContext.writeSheetHolder().getCachedSheet(); - Map> firstRowCache = new HashMap>(8); + Map> firstRowCache = MapUtils.newHashMapWithExpectedSize(8); for (int i = 0; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row == null) { @@ -392,14 +399,14 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { /** * To prepare data * - * @param cell - * @param rowIndex - * @param columnIndex - * @param firstRowCache + * @param cell cell + * @param rowIndex row index + * @param columnIndex column index + * @param firstRowCache first row cache * @return Returns the data that the cell needs to replace */ private String prepareData(Cell cell, int rowIndex, int columnIndex, Map> firstRowCache) { - if (!CellType.STRING.equals(cell.getCellTypeEnum())) { + if (!CellType.STRING.equals(cell.getCellType())) { return null; } String value = cell.getStringCellValue(); @@ -412,10 +419,11 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { int startIndex = 0; int length = value.length(); int lastPrepareDataIndex = 0; - out: while (startIndex < length) { + out: + while (startIndex < length) { int prefixIndex = value.indexOf(FILL_PREFIX, startIndex); if (prefixIndex < 0) { - break out; + break; } if (prefixIndex != 0) { char prefixPrefixChar = value.charAt(prefixIndex - 1); @@ -457,6 +465,10 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { analysisCell.getVariableList().add(variable); if (lastPrepareDataIndex == prefixIndex) { analysisCell.getPrepareDataList().add(StringUtils.EMPTY); + // fix https://github.com/alibaba/easyexcel/issues/2035 + if (lastPrepareDataIndex != 0) { + analysisCell.setOnlyOneVariable(Boolean.FALSE); + } } else { String data = convertPrepareData(value.substring(lastPrepareDataIndex, prefixIndex)); preparedData.append(data); @@ -465,6 +477,12 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { } lastPrepareDataIndex = suffixIndex + 1; } + // fix https://github.com/alibaba/easyexcel/issues/1552 + // When read template, XLSX data may be in `is` labels, and set the time set in `v` label, lead to can't set + // up successfully, so all data format to empty first. + if (analysisCell != null && CollectionUtils.isNotEmpty(analysisCell.getVariableList())) { + cell.setBlank(); + } return dealAnalysisCell(analysisCell, value, rowIndex, lastPrepareDataIndex, length, firstRowCache, preparedData); } @@ -480,28 +498,21 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { } String uniqueDataFlag = uniqueDataFlag(writeContext.writeSheetHolder(), analysisCell.getPrefix()); if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) { - List analysisCellList = templateAnalysisCache.get(uniqueDataFlag); - if (analysisCellList == null) { - analysisCellList = new ArrayList(); - templateAnalysisCache.put(uniqueDataFlag, analysisCellList); - } + List analysisCellList = templateAnalysisCache.computeIfAbsent(uniqueDataFlag, + key -> ListUtils.newArrayList()); analysisCellList.add(analysisCell); } else { - Set uniqueFirstRowCache = firstRowCache.get(uniqueDataFlag); - if (uniqueFirstRowCache == null) { - uniqueFirstRowCache = new HashSet(); - firstRowCache.put(uniqueDataFlag, uniqueFirstRowCache); - } + Set uniqueFirstRowCache = firstRowCache.computeIfAbsent(uniqueDataFlag, + key -> new HashSet<>()); + if (!uniqueFirstRowCache.contains(rowIndex)) { analysisCell.setFirstRow(Boolean.TRUE); uniqueFirstRowCache.add(rowIndex); } - List collectionAnalysisCellList = templateCollectionAnalysisCache.get(uniqueDataFlag); - if (collectionAnalysisCellList == null) { - collectionAnalysisCellList = new ArrayList(); - templateCollectionAnalysisCache.put(uniqueDataFlag, collectionAnalysisCellList); - } + List collectionAnalysisCellList = templateCollectionAnalysisCache.computeIfAbsent( + uniqueDataFlag, key -> ListUtils.newArrayList()); + collectionAnalysisCellList.add(analysisCell); } return preparedData.toString(); @@ -514,9 +525,9 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { analysisCell.setRowIndex(rowIndex); analysisCell.setColumnIndex(columnIndex); analysisCell.setOnlyOneVariable(Boolean.TRUE); - List variableList = new ArrayList(); + List variableList = ListUtils.newArrayList(); analysisCell.setVariableList(variableList); - List prepareDataList = new ArrayList(); + List prepareDataList = ListUtils.newArrayList(); analysisCell.setPrepareDataList(prepareDataList); analysisCell.setCellType(WriteTemplateAnalysisCellTypeEnum.COMMON); analysisCell.setFirstRow(Boolean.FALSE); @@ -534,7 +545,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { if (writeSheetHolder.getSheetNo() != null) { prefix = writeSheetHolder.getSheetNo().toString(); } else { - prefix = writeSheetHolder.getSheetName().toString(); + prefix = writeSheetHolder.getSheetName(); } if (StringUtils.isEmpty(wrapperName)) { return prefix + "-"; diff --git a/src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java index b649af7a..688598ac 100644 --- a/src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java @@ -2,19 +2,21 @@ package com.alibaba.excel.write.handler; import java.util.List; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; - -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; + /** * Abstract cell write handler * * @author Jiaju Zhuang + * @deprecated Please use it directly {@link CellWriteHandler} **/ +@Deprecated public abstract class AbstractCellWriteHandler implements CellWriteHandler { @Override @@ -31,13 +33,12 @@ public abstract class AbstractCellWriteHandler implements CellWriteHandler { @Override public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { - + WriteCellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } } diff --git a/src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java index d1e8c3a9..286d8757 100644 --- a/src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java @@ -1,15 +1,17 @@ package com.alibaba.excel.write.handler; -import org.apache.poi.ss.usermodel.Row; - import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Row; + /** * Abstract row write handler * * @author Jiaju Zhuang + * @deprecated Please use it directly {@link RowWriteHandler} **/ +@Deprecated public abstract class AbstractRowWriteHandler implements RowWriteHandler { @Override public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, diff --git a/src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java index 76f4c846..d24f9010 100644 --- a/src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java @@ -7,7 +7,9 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; * Abstract sheet write handler * * @author Jiaju Zhuang + * @deprecated Please use it directly {@link SheetWriteHandler} **/ +@Deprecated public abstract class AbstractSheetWriteHandler implements SheetWriteHandler { @Override public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { diff --git a/src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java index baad3920..5bb2fc5f 100644 --- a/src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java @@ -6,7 +6,9 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; * Abstract workbook write handler * * @author Jiaju Zhuang + * @deprecated Please use it directly {@link WorkbookWriteHandler} **/ +@Deprecated public abstract class AbstractWorkbookWriteHandler implements WorkbookWriteHandler { @Override diff --git a/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java index 8701d6a0..fd144e1c 100644 --- a/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java @@ -2,14 +2,16 @@ package com.alibaba.excel.write.handler; import java.util.List; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; - -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; + /** * intercepts handle cell creation * @@ -17,76 +19,100 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; */ public interface CellWriteHandler extends WriteHandler { + /** + * Called before create the cell + * + * @param context + */ + default void beforeCellCreate(CellWriteHandlerContext context) { + beforeCellCreate(context.getWriteSheetHolder(), context.getWriteTableHolder(), context.getRow(), + context.getHeadData(), context.getColumnIndex(), context.getRelativeRowIndex(), context.getHead()); + } + /** * Called before create the cell * * @param writeSheetHolder - * @param writeTableHolder - * Nullable.It is null without using table writes. + * @param writeTableHolder Nullable.It is null without using table writes. * @param row - * @param head - * Nullable.It is null in the case of fill data and without head. + * @param head Nullable.It is null in the case of fill data and without head. * @param columnIndex - * @param relativeRowIndex - * Nullable.It is null in the case of fill data. - * @param isHead - * It will always be false when fill data. + * @param relativeRowIndex Nullable.It is null in the case of fill data. + * @param isHead It will always be false when fill data. + */ + default void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, + Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {} + + /** + * Called after the cell is created + * + * @param context */ - void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, - Integer columnIndex, Integer relativeRowIndex, Boolean isHead); + default void afterCellCreate(CellWriteHandlerContext context) { + afterCellCreate(context.getWriteSheetHolder(), context.getWriteTableHolder(), context.getCell(), + context.getHeadData(), context.getRelativeRowIndex(), context.getHead()); + } /** * Called after the cell is created * * @param writeSheetHolder - * @param writeTableHolder - * Nullable.It is null without using table writes. + * @param writeTableHolder Nullable.It is null without using table writes. * @param cell - * @param head - * Nullable.It is null in the case of fill data and without head. - * @param relativeRowIndex - * Nullable.It is null in the case of fill data. - * @param isHead - * It will always be false when fill data. + * @param head Nullable.It is null in the case of fill data and without head. + * @param relativeRowIndex Nullable.It is null in the case of fill data. + * @param isHead It will always be false when fill data. */ - void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, - Integer relativeRowIndex, Boolean isHead); + default void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) {} + + /** + * Called after the cell data is converted + * + * @param context + */ + default void afterCellDataConverted(CellWriteHandlerContext context) { + WriteCellData writeCellData = CollectionUtils.isNotEmpty(context.getCellDataList()) ? context + .getCellDataList().get(0) : null; + afterCellDataConverted(context.getWriteSheetHolder(), context.getWriteTableHolder(), writeCellData, + context.getCell(), context.getHeadData(), context.getRelativeRowIndex(), context.getHead()); + } /** * Called after the cell data is converted * * @param writeSheetHolder - * @param writeTableHolder - * Nullable.It is null without using table writes. + * @param writeTableHolder Nullable.It is null without using table writes. * @param cell - * @param head - * Nullable.It is null in the case of fill data and without head. - * @param cellData - * Nullable.It is null in the case of add header. - * @param relativeRowIndex - * Nullable.It is null in the case of fill data. - * @param isHead - * It will always be false when fill data. + * @param head Nullable.It is null in the case of fill data and without head. + * @param cellData Nullable.It is null in the case of add header. + * @param relativeRowIndex Nullable.It is null in the case of fill data. + * @param isHead It will always be false when fill data. + */ + default void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + WriteCellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {} + + /** + * Called after all operations on the cell have been completed + * + * @param context */ - void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, - Cell cell, Head head, Integer relativeRowIndex, Boolean isHead); + default void afterCellDispose(CellWriteHandlerContext context) { + afterCellDispose(context.getWriteSheetHolder(), context.getWriteTableHolder(), context.getCellDataList(), + context.getCell(), context.getHeadData(), context.getRelativeRowIndex(), context.getHead()); + } /** * Called after all operations on the cell have been completed * * @param writeSheetHolder - * @param writeTableHolder - * Nullable.It is null without using table writes. + * @param writeTableHolder Nullable.It is null without using table writes. * @param cell - * @param head - * Nullable.It is null in the case of fill data and without head. - * @param cellDataList - * Nullable.It is null in the case of add header.There may be several when fill the data. - * @param relativeRowIndex - * Nullable.It is null in the case of fill data. - * @param isHead - * It will always be false when fill data. + * @param head Nullable.It is null in the case of fill data and without head. + * @param cellDataList Nullable.It is null in the case of add header.There may be several when fill the data. + * @param relativeRowIndex Nullable.It is null in the case of fill data. + * @param isHead It will always be false when fill data. */ - void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead); + default void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {} } diff --git a/src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java b/src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java index dff84d7a..284397b6 100644 --- a/src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java +++ b/src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java @@ -3,12 +3,19 @@ package com.alibaba.excel.write.handler; import java.util.ArrayList; import java.util.List; -import org.apache.poi.ss.usermodel.IndexedColors; - +import com.alibaba.excel.write.handler.impl.DefaultRowWriteHandler; +import com.alibaba.excel.write.handler.impl.DimensionWorkbookWriteHandler; +import com.alibaba.excel.write.handler.impl.FillStyleCellWriteHandler; 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.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.VerticalAlignment; + /** * Load default handler * @@ -16,23 +23,41 @@ import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; */ public class DefaultWriteHandlerLoader { + public static final List DEFAULT_WRITE_HANDLER_LIST = new ArrayList<>(); + + static { + DEFAULT_WRITE_HANDLER_LIST.add(new DimensionWorkbookWriteHandler()); + DEFAULT_WRITE_HANDLER_LIST.add(new DefaultRowWriteHandler()); + DEFAULT_WRITE_HANDLER_LIST.add(new FillStyleCellWriteHandler()); + } + /** * Load default handler * * @return */ public static List loadDefaultHandler(Boolean useDefaultStyle) { - List handlerList = new ArrayList(); + List handlerList = new ArrayList<>(); if (useDefaultStyle) { WriteCellStyle headWriteCellStyle = new WriteCellStyle(); + headWriteCellStyle.setWrapped(true); + headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); + headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + headWriteCellStyle.setLocked(true); + headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + headWriteCellStyle.setBorderTop(BorderStyle.THIN); + headWriteCellStyle.setBorderBottom(BorderStyle.THIN); + headWriteCellStyle.setBorderLeft(BorderStyle.THIN); + headWriteCellStyle.setBorderRight(BorderStyle.THIN); WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontName("宋体"); headWriteFont.setFontHeightInPoints((short)14); headWriteFont.setBold(true); headWriteCellStyle.setWriteFont(headWriteFont); - handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList())); + handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList<>())); } + handlerList.addAll(DEFAULT_WRITE_HANDLER_LIST); return handlerList; } diff --git a/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java index 29ac10b0..afef0c97 100644 --- a/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java @@ -1,10 +1,11 @@ package com.alibaba.excel.write.handler; -import org.apache.poi.ss.usermodel.Row; - +import com.alibaba.excel.write.handler.context.RowWriteHandlerContext; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Row; + /** * intercepts handle row creation * @@ -12,48 +13,69 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; */ public interface RowWriteHandler extends WriteHandler { + /** + * Called before create the row + * + * @param context + */ + default void beforeRowCreate(RowWriteHandlerContext context) { + beforeRowCreate(context.getWriteSheetHolder(), context.getWriteTableHolder(), context.getRowIndex(), + context.getRelativeRowIndex(), context.getHead()); + } + /** * Called before create the row * * @param writeSheetHolder - * @param writeTableHolder - * Nullable.It is null without using table writes. + * @param writeTableHolder Nullable.It is null without using table writes. * @param rowIndex - * @param relativeRowIndex - * Nullable.It is null in the case of fill data. - * @param isHead - * Nullable.It is null in the case of fill data. + * @param relativeRowIndex Nullable.It is null in the case of fill data. + * @param isHead Nullable.It is null in the case of fill data. */ - void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, - Integer relativeRowIndex, Boolean isHead); + default void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, + Integer relativeRowIndex, Boolean isHead) {} + + /** + * Called after the row is created + * + * @param context + */ + default void afterRowCreate(RowWriteHandlerContext context) { + afterRowCreate(context.getWriteSheetHolder(), context.getWriteTableHolder(), context.getRow(), + context.getRelativeRowIndex(), context.getHead()); + } /** * Called after the row is created * * @param writeSheetHolder - * @param writeTableHolder - * Nullable.It is null without using table writes. + * @param writeTableHolder Nullable.It is null without using table writes. * @param row - * @param relativeRowIndex - * Nullable.It is null in the case of fill data. - * @param isHead - * Nullable.It is null in the case of fill data. + * @param relativeRowIndex Nullable.It is null in the case of fill data. + * @param isHead Nullable.It is null in the case of fill data. + */ + default void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, + Integer relativeRowIndex, Boolean isHead) {} + + /** + * Called after all operations on the row have been completed.This method is not called when fill the data. + * + * @param context */ - void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Integer relativeRowIndex, Boolean isHead); + default void afterRowDispose(RowWriteHandlerContext context) { + afterRowDispose(context.getWriteSheetHolder(), context.getWriteTableHolder(), context.getRow(), + context.getRelativeRowIndex(), context.getHead()); + } /** * Called after all operations on the row have been completed.This method is not called when fill the data. * * @param writeSheetHolder - * @param writeTableHolder - * Nullable.It is null without using table writes. + * @param writeTableHolder Nullable.It is null without using table writes. * @param row - * @param relativeRowIndex - * Nullable.It is null in the case of fill data. - * @param isHead - * Nullable.It is null in the case of fill data. + * @param relativeRowIndex Nullable.It is null in the case of fill data. + * @param isHead Nullable.It is null in the case of fill data. */ - void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Integer relativeRowIndex, Boolean isHead); + default void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, + Integer relativeRowIndex, Boolean isHead) {} } diff --git a/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java index b97e1d15..67672b7d 100644 --- a/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java @@ -1,5 +1,6 @@ package com.alibaba.excel.write.handler; +import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; @@ -10,13 +11,31 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; */ public interface SheetWriteHandler extends WriteHandler { + /** + * Called before create the sheet + * + * @param context + */ + default void beforeSheetCreate(SheetWriteHandlerContext context) { + beforeSheetCreate(context.getWriteWorkbookHolder(), context.getWriteSheetHolder()); + } + /** * Called before create the sheet * * @param writeWorkbookHolder * @param writeSheetHolder */ - void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder); + default void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {} + + /** + * Called after the sheet is created + * + * @param context + */ + default void afterSheetCreate(SheetWriteHandlerContext context) { + afterSheetCreate(context.getWriteWorkbookHolder(), context.getWriteSheetHolder()); + } /** * Called after the sheet is created @@ -24,5 +43,5 @@ public interface SheetWriteHandler extends WriteHandler { * @param writeWorkbookHolder * @param writeSheetHolder */ - void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder); + default void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {} } diff --git a/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java index 8dba9646..140d226c 100644 --- a/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java @@ -1,5 +1,6 @@ package com.alibaba.excel.write.handler; +import com.alibaba.excel.write.handler.context.WorkbookWriteHandlerContext; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; /** @@ -9,22 +10,49 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; */ public interface WorkbookWriteHandler extends WriteHandler { + /** + * Called before create the workbook + * + * @param context + */ + default void beforeWorkbookCreate(WorkbookWriteHandlerContext context) { + beforeWorkbookCreate(); + } + /** * Called before create the workbook */ - void beforeWorkbookCreate(); + default void beforeWorkbookCreate() {} + + /** + * Called after the workbook is created + * + * @param context + */ + default void afterWorkbookCreate(WorkbookWriteHandlerContext context) { + afterWorkbookCreate(context.getWriteWorkbookHolder()); + } /** * Called after the workbook is created * * @param writeWorkbookHolder */ - void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder); + default void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {} + + /** + * Called after all operations on the workbook have been completed + * + * @param context + */ + default void afterWorkbookDispose(WorkbookWriteHandlerContext context) { + afterWorkbookDispose(context.getWriteWorkbookHolder()); + } /** * Called after all operations on the workbook have been completed * * @param writeWorkbookHolder */ - void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder); + default void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {} } diff --git a/src/main/java/com/alibaba/excel/write/handler/context/CellWriteHandlerContext.java b/src/main/java/com/alibaba/excel/write/handler/context/CellWriteHandlerContext.java new file mode 100644 index 00000000..6dd9a988 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/context/CellWriteHandlerContext.java @@ -0,0 +1,69 @@ +package com.alibaba.excel.write.handler.context; + +import java.util.List; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; + +/** + * cell context + * + * @author Jiaju Zhuang + */ +@Data +@AllArgsConstructor +public class CellWriteHandlerContext { + /** + * write context + */ + private WriteContext writeContext; + /** + * workbook + */ + private WriteWorkbookHolder writeWorkbookHolder; + /** + * sheet + */ + private WriteSheetHolder writeSheetHolder; + /** + * table .Nullable.It is null without using table writes. + */ + private WriteTableHolder writeTableHolder; + /** + * row + */ + private Row row; + /** + * cell + */ + private Cell cell; + /** + * index + */ + private Integer columnIndex; + /** + * Nullable.It is null in the case of fill data. + */ + private Integer relativeRowIndex; + /** + * Nullable.It is null in the case of fill data. + */ + private Head headData; + /** + * Nullable.It is null in the case of add header.There may be several when fill the data. + */ + private List> cellDataList; + /** + * Nullable.It is null in the case of fill data. + */ + private Boolean head; +} diff --git a/src/main/java/com/alibaba/excel/write/handler/context/RowWriteHandlerContext.java b/src/main/java/com/alibaba/excel/write/handler/context/RowWriteHandlerContext.java new file mode 100644 index 00000000..6578d3a2 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/context/RowWriteHandlerContext.java @@ -0,0 +1,52 @@ +package com.alibaba.excel.write.handler.context; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.apache.poi.ss.usermodel.Row; + +/** + * row context + * + * @author Jiaju Zhuang + */ +@Data +@AllArgsConstructor +public class RowWriteHandlerContext { + /** + * write context + */ + private WriteContext writeContext; + /** + * workbook + */ + private WriteWorkbookHolder writeWorkbookHolder; + /** + * sheet + */ + private WriteSheetHolder writeSheetHolder; + /** + * table .Nullable.It is null without using table writes. + */ + private WriteTableHolder writeTableHolder; + /** + * row index + */ + private Integer rowIndex; + /** + * row + */ + private Row row; + /** + * Nullable.It is null in the case of fill data. + */ + private Integer relativeRowIndex; + /** + * Nullable.It is null in the case of fill data. + */ + private Boolean head; +} diff --git a/src/main/java/com/alibaba/excel/write/handler/context/SheetWriteHandlerContext.java b/src/main/java/com/alibaba/excel/write/handler/context/SheetWriteHandlerContext.java new file mode 100644 index 00000000..c1164eb0 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/context/SheetWriteHandlerContext.java @@ -0,0 +1,30 @@ +package com.alibaba.excel.write.handler.context; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * sheet context + * + * @author Jiaju Zhuang + */ +@Data +@AllArgsConstructor +public class SheetWriteHandlerContext { + /** + * write context + */ + private WriteContext writeContext; + /** + * workbook + */ + private WriteWorkbookHolder writeWorkbookHolder; + /** + * sheet + */ + private WriteSheetHolder writeSheetHolder; +} diff --git a/src/main/java/com/alibaba/excel/write/handler/context/WorkbookWriteHandlerContext.java b/src/main/java/com/alibaba/excel/write/handler/context/WorkbookWriteHandlerContext.java new file mode 100644 index 00000000..f955d4bf --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/context/WorkbookWriteHandlerContext.java @@ -0,0 +1,25 @@ +package com.alibaba.excel.write.handler.context; + +import com.alibaba.excel.context.WriteContext; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * workbook context + * + * @author Jiaju Zhuang + */ +@Data +@AllArgsConstructor +public class WorkbookWriteHandlerContext { + /** + * write context + */ + private WriteContext writeContext; + /** + * workbook + */ + private WriteWorkbookHolder writeWorkbookHolder; +} diff --git a/src/main/java/com/alibaba/excel/write/handler/impl/DefaultRowWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/impl/DefaultRowWriteHandler.java new file mode 100644 index 00000000..2d1f3f77 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/impl/DefaultRowWriteHandler.java @@ -0,0 +1,21 @@ +package com.alibaba.excel.write.handler.impl; + +import com.alibaba.excel.write.handler.RowWriteHandler; +import com.alibaba.excel.write.handler.context.RowWriteHandlerContext; + +import lombok.extern.slf4j.Slf4j; + +/** + * Default row handler. + * + * @author Jiaju Zhuang + */ +@Slf4j +public class DefaultRowWriteHandler implements RowWriteHandler { + + @Override + public void afterRowDispose(RowWriteHandlerContext context) { + context.getWriteSheetHolder().setLastRowIndex(context.getRowIndex()); + } + +} diff --git a/src/main/java/com/alibaba/excel/write/handler/impl/DimensionWorkbookWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/impl/DimensionWorkbookWriteHandler.java new file mode 100644 index 00000000..6b444a47 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/impl/DimensionWorkbookWriteHandler.java @@ -0,0 +1,81 @@ +package com.alibaba.excel.write.handler.impl; + +import java.lang.reflect.Field; +import java.util.Map; + +import com.alibaba.excel.util.FieldUtils; +import com.alibaba.excel.write.handler.WorkbookWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.MapUtils; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; + +/** + * Handle the problem of unable to write dimension. + * + * https://github.com/alibaba/easyexcel/issues/1282 + * + * @author Jiaju Zhuang + */ +@Slf4j +public class DimensionWorkbookWriteHandler implements WorkbookWriteHandler { + + private static final String XSSF_SHEET_MEMBER_VARIABLE_NAME = "_sh"; + private static final Field XSSF_SHEET_FIELD = FieldUtils.getField(SXSSFSheet.class, XSSF_SHEET_MEMBER_VARIABLE_NAME, + true); + + @Override + public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) { + if (writeWorkbookHolder == null || writeWorkbookHolder.getWorkbook() == null) { + return; + } + if (!(writeWorkbookHolder.getWorkbook() instanceof SXSSFWorkbook)) { + return; + } + + Map writeSheetHolderMap = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap(); + if (MapUtils.isEmpty(writeSheetHolderMap)) { + return; + } + for (WriteSheetHolder writeSheetHolder : writeSheetHolderMap.values()) { + if (writeSheetHolder.getSheet() == null || !(writeSheetHolder.getSheet() instanceof SXSSFSheet)) { + continue; + } + SXSSFSheet sxssfSheet = ((SXSSFSheet)writeSheetHolder.getSheet()); + XSSFSheet xssfSheet; + try { + xssfSheet = (XSSFSheet)XSSF_SHEET_FIELD.get(sxssfSheet); + } catch (IllegalAccessException e) { + log.debug("Can not found _sh.", e); + continue; + } + if (xssfSheet == null) { + continue; + } + CTWorksheet ctWorksheet = xssfSheet.getCTWorksheet(); + if (ctWorksheet == null) { + continue; + } + int headSize = 0; + if (MapUtils.isNotEmpty(writeSheetHolder.getExcelWriteHeadProperty().getHeadMap())) { + headSize = writeSheetHolder.getExcelWriteHeadProperty().getHeadMap().size(); + if (headSize > 0) { + headSize--; + } + } + Integer lastRowIndex = writeSheetHolder.getLastRowIndex(); + if (lastRowIndex == null) { + lastRowIndex = 0; + } + + ctWorksheet.getDimension().setRef( + "A1:" + CellReference.convertNumToColString(headSize) + (lastRowIndex + 1)); + } + } +} diff --git a/src/main/java/com/alibaba/excel/write/handler/impl/FillStyleCellWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/impl/FillStyleCellWriteHandler.java new file mode 100644 index 00000000..9956ea19 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/impl/FillStyleCellWriteHandler.java @@ -0,0 +1,43 @@ +package com.alibaba.excel.write.handler.impl; + +import java.util.List; + +import com.alibaba.excel.constant.OrderConstant; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; + +/** + * fill cell style. + * + * @author Jiaju Zhuang + */ +@Slf4j +public class FillStyleCellWriteHandler implements CellWriteHandler { + + @Override + public int order() { + return OrderConstant.FILL_STYLE; + } + + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + List> cellDataList = context.getCellDataList(); + if (CollectionUtils.isEmpty(cellDataList) || cellDataList.size() > 1) { + return; + } + WriteCellData cellData = cellDataList.get(0); + WriteCellStyle writeCellStyle = cellData.getWriteCellStyle(); + if (writeCellStyle == null) { + return; + } + WriteWorkbookHolder writeWorkbookHolder = context.getWriteWorkbookHolder(); + context.getCell().setCellStyle(writeWorkbookHolder.createCellStyle(writeCellStyle)); + } + +} diff --git a/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java index 2a2b7b6d..70db8a01 100644 --- a/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java +++ b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java @@ -1,47 +1,26 @@ package com.alibaba.excel.write.merge; -import java.util.List; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; -import com.alibaba.excel.metadata.CellData; -import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.write.handler.CellWriteHandler; -import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteTableHolder; - /** * Merge strategy * * @author Jiaju Zhuang */ public abstract class AbstractMergeStrategy implements CellWriteHandler { - @Override - public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { - - } - - @Override - public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, - Head head, Integer relativeRowIndex, Boolean isHead) {} - - @Override - public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, - WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, - Boolean isHead) { - - } @Override - public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { - if (isHead) { + public void afterCellDispose(CellWriteHandlerContext context) { + if (context.getHead()) { return; } - merge(writeSheetHolder.getSheet(), cell, head, relativeRowIndex); + merge(context.getWriteSheetHolder().getSheet(), context.getCell(), context.getHeadData(), + context.getRelativeRowIndex()); } /** diff --git a/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java index 5796dde5..13ebe3cb 100644 --- a/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java +++ b/src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java @@ -5,6 +5,7 @@ import org.apache.poi.ss.util.CellRangeAddress; import com.alibaba.excel.metadata.property.LoopMergeProperty; import com.alibaba.excel.write.handler.AbstractRowWriteHandler; +import com.alibaba.excel.write.handler.RowWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; @@ -13,7 +14,7 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; * * @author Jiaju Zhuang */ -public class LoopMergeStrategy extends AbstractRowWriteHandler { +public class LoopMergeStrategy implements RowWriteHandler { /** * Each row */ diff --git a/src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java index d85781e1..0fe3dd61 100644 --- a/src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java +++ b/src/main/java/com/alibaba/excel/write/merge/OnceAbsoluteMergeStrategy.java @@ -4,6 +4,7 @@ import org.apache.poi.ss.util.CellRangeAddress; import com.alibaba.excel.metadata.property.OnceAbsoluteMergeProperty; import com.alibaba.excel.write.handler.AbstractSheetWriteHandler; +import com.alibaba.excel.write.handler.SheetWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; @@ -12,7 +13,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; * * @author Jiaju Zhuang */ -public class OnceAbsoluteMergeStrategy extends AbstractSheetWriteHandler { +public class OnceAbsoluteMergeStrategy implements SheetWriteHandler { /** * First row */ diff --git a/src/main/java/com/alibaba/excel/write/metadata/CollectionRowData.java b/src/main/java/com/alibaba/excel/write/metadata/CollectionRowData.java new file mode 100644 index 00000000..bf98f5c5 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/metadata/CollectionRowData.java @@ -0,0 +1,32 @@ +package com.alibaba.excel.write.metadata; + +import java.util.Collection; + +/** + * A collection row of data. + * + * @author Jiaju Zhuang + */ +public class CollectionRowData implements RowData { + + private final Object[] array; + + public CollectionRowData(Collection collection) { + this.array = collection.toArray(); + } + + @Override + public Object get(int index) { + return array[index]; + } + + @Override + public int size() { + return array.length; + } + + @Override + public boolean isEmpty() { + return array.length == 0; + } +} diff --git a/src/main/java/com/alibaba/excel/write/metadata/MapRowData.java b/src/main/java/com/alibaba/excel/write/metadata/MapRowData.java new file mode 100644 index 00000000..409fc58d --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/metadata/MapRowData.java @@ -0,0 +1,33 @@ +package com.alibaba.excel.write.metadata; + +import java.util.Map; + +/** + * A map row of data. + * + * @author Jiaju Zhuang + */ +public class MapRowData implements RowData { + + private final Map map; + + public MapRowData(Map map) { + this.map = map; + } + + @Override + public Object get(int index) { + return map.get(index); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + +} diff --git a/src/main/java/com/alibaba/excel/write/metadata/RowData.java b/src/main/java/com/alibaba/excel/write/metadata/RowData.java new file mode 100644 index 00000000..cb86a3e0 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/metadata/RowData.java @@ -0,0 +1,35 @@ +package com.alibaba.excel.write.metadata; + +/** + * A row of data. + * + * @author Jiaju Zhuang + */ +public interface RowData { + + /** + * Returns the value to which the specified key is mapped, + * or {@code null} if this map contains no mapping for the key. + * + * @param index + * @return data + */ + Object get(int index); + + /** + * Returns the number of elements in this collection. If this collection + * contains more than Integer.MAX_VALUE elements, returns + * Integer.MAX_VALUE. + * + * @return the number of elements in this collection + */ + int size(); + + /** + * Returns true if this collection contains no elements. + * + * @return true if this collection contains no elements + */ + boolean isEmpty(); + +} diff --git a/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java b/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java index b582576e..91527cc1 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java +++ b/src/main/java/com/alibaba/excel/write/metadata/WriteBasicParameter.java @@ -7,11 +7,14 @@ import java.util.List; import com.alibaba.excel.metadata.BasicParameter; import com.alibaba.excel.write.handler.WriteHandler; +import lombok.Data; + /** * Write basic parameter * * @author Jiaju Zhuang **/ +@Data public class WriteBasicParameter extends BasicParameter { /** * Writes the head relative to the existing contents of the sheet. Indexes are zero-based. @@ -40,7 +43,7 @@ public class WriteBasicParameter extends BasicParameter { /** * Ignore the custom columns. */ - private Collection excludeColumnFiledNames; + private Collection excludeColumnFieldNames; /** * Only output the custom columns. */ @@ -48,78 +51,5 @@ public class WriteBasicParameter extends BasicParameter { /** * Only output the custom columns. */ - private Collection includeColumnFiledNames; - - public Integer getRelativeHeadRowIndex() { - return relativeHeadRowIndex; - } - - public void setRelativeHeadRowIndex(Integer relativeHeadRowIndex) { - this.relativeHeadRowIndex = relativeHeadRowIndex; - } - - public Boolean getNeedHead() { - return needHead; - } - - public void setNeedHead(Boolean needHead) { - this.needHead = needHead; - } - - public List getCustomWriteHandlerList() { - return customWriteHandlerList; - } - - public void setCustomWriteHandlerList(List customWriteHandlerList) { - this.customWriteHandlerList = customWriteHandlerList; - } - - public Boolean getUseDefaultStyle() { - return useDefaultStyle; - } - - public void setUseDefaultStyle(Boolean useDefaultStyle) { - this.useDefaultStyle = useDefaultStyle; - } - - public Boolean getAutomaticMergeHead() { - return automaticMergeHead; - } - - public void setAutomaticMergeHead(Boolean automaticMergeHead) { - this.automaticMergeHead = automaticMergeHead; - } - - public Collection getExcludeColumnIndexes() { - return excludeColumnIndexes; - } - - public void setExcludeColumnIndexes(Collection excludeColumnIndexes) { - this.excludeColumnIndexes = excludeColumnIndexes; - } - - public Collection getExcludeColumnFiledNames() { - return excludeColumnFiledNames; - } - - public void setExcludeColumnFiledNames(Collection excludeColumnFiledNames) { - this.excludeColumnFiledNames = excludeColumnFiledNames; - } - - public Collection getIncludeColumnIndexes() { - return includeColumnIndexes; - } - - public void setIncludeColumnIndexes(Collection includeColumnIndexes) { - this.includeColumnIndexes = includeColumnIndexes; - } - - public Collection getIncludeColumnFiledNames() { - return includeColumnFiledNames; - } - - public void setIncludeColumnFiledNames(Collection includeColumnFiledNames) { - this.includeColumnFiledNames = includeColumnFiledNames; - } - + private Collection includeColumnFieldNames; } diff --git a/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java b/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java index 62fac752..04bfb822 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java +++ b/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java @@ -1,17 +1,13 @@ package com.alibaba.excel.write.metadata; -import java.util.HashMap; -import java.util.Map; - -import com.alibaba.excel.metadata.TableStyle; -import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; -import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import lombok.Data; /** * Write sheet * * @author jipengfei */ +@Data public class WriteSheet extends WriteBasicParameter { /** * Starting from 0 @@ -21,54 +17,4 @@ public class WriteSheet extends WriteBasicParameter { * sheet name */ private String sheetName; - /** - * column with - * - * @deprecated please use {@link SimpleColumnWidthStyleStrategy} - */ - @Deprecated - private Map columnWidthMap = new HashMap(); - /** - * - * @deprecated please use{@link HorizontalCellStyleStrategy} - */ - @Deprecated - private TableStyle tableStyle; - - public Integer getSheetNo() { - return sheetNo; - } - - public void setSheetNo(Integer sheetNo) { - this.sheetNo = sheetNo; - } - - public String getSheetName() { - return sheetName; - } - - public void setSheetName(String sheetName) { - this.sheetName = sheetName; - } - - public Map getColumnWidthMap() { - return columnWidthMap; - } - - public void setColumnWidthMap(Map columnWidthMap) { - this.columnWidthMap = columnWidthMap; - } - - public TableStyle getTableStyle() { - return tableStyle; - } - - public void setTableStyle(TableStyle tableStyle) { - this.tableStyle = tableStyle; - } - - @Override - public String toString() { - return "WriteSheet{" + "sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' + "} " + super.toString(); - } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/WriteTable.java b/src/main/java/com/alibaba/excel/write/metadata/WriteTable.java index ec7933c0..a935f326 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/WriteTable.java +++ b/src/main/java/com/alibaba/excel/write/metadata/WriteTable.java @@ -1,38 +1,16 @@ package com.alibaba.excel.write.metadata; -import com.alibaba.excel.metadata.TableStyle; -import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import lombok.Data; /** * table * * @author jipengfei */ +@Data public class WriteTable extends WriteBasicParameter { /** * Starting from 0 */ private Integer tableNo; - /** - * - * @deprecated please use{@link HorizontalCellStyleStrategy} - */ - @Deprecated - private TableStyle tableStyle; - - public Integer getTableNo() { - return tableNo; - } - - public void setTableNo(Integer tableNo) { - this.tableNo = tableNo; - } - - public TableStyle getTableStyle() { - return tableStyle; - } - - public void setTableStyle(TableStyle tableStyle) { - this.tableStyle = tableStyle; - } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java b/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java index c28e0412..bcc39211 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java +++ b/src/main/java/com/alibaba/excel/write/metadata/WriteWorkbook.java @@ -3,15 +3,18 @@ package com.alibaba.excel.write.metadata; import java.io.File; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.Charset; import com.alibaba.excel.support.ExcelTypeEnum; -import com.alibaba.excel.write.handler.WriteHandler; + +import lombok.Data; /** * Workbook * * @author Jiaju Zhuang **/ +@Data public class WriteWorkbook extends WriteBasicParameter { /** * Excel type.The default is xlsx @@ -20,26 +23,30 @@ public class WriteWorkbook extends WriteBasicParameter { /** * Final output file *

- * If 'outputStream' and 'file' all not empty,file first + * If 'outputStream' and 'file' all not empty, file first */ private File file; /** * Final output stream *

- * If 'outputStream' and 'file' all not empty,file first + * If 'outputStream' and 'file' all not empty, file first */ private OutputStream outputStream; + /** + * output charset + */ + private Charset charset; /** * Template input stream *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private InputStream templateInputStream; /** * Template file *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private File templateFile; /** @@ -58,7 +65,7 @@ public class WriteWorkbook extends WriteBasicParameter { */ private String password; /** - * Write excel in memory. Default false,the cache file is created and finally written to excel. + * Write excel in memory. Default false, the cache file is created and finally written to excel. *

* Comment and RichTextString are only supported in memory mode. */ @@ -67,118 +74,4 @@ public class WriteWorkbook extends WriteBasicParameter { * Excel is also written in the event of an exception being thrown.The default false. */ private Boolean writeExcelOnException; - /** - * The default is all excel objects.Default is true. - *

- * if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a field. - *

- * if false , you must use {@link com.alibaba.excel.annotation.ExcelProperty} to use a filed. - * - * @deprecated Just to be compatible with historical data, The default is always going to be convert all filed. - */ - @Deprecated - private Boolean convertAllFiled; - /** - * Write handler - * - * @deprecated please use {@link WriteHandler} - */ - @Deprecated - private com.alibaba.excel.event.WriteHandler writeHandler; - - public ExcelTypeEnum getExcelType() { - return excelType; - } - - public void setExcelType(ExcelTypeEnum excelType) { - this.excelType = excelType; - } - - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - - public OutputStream getOutputStream() { - return outputStream; - } - - public void setOutputStream(OutputStream outputStream) { - this.outputStream = outputStream; - } - - public InputStream getTemplateInputStream() { - return templateInputStream; - } - - public void setTemplateInputStream(InputStream templateInputStream) { - this.templateInputStream = templateInputStream; - } - - public File getTemplateFile() { - return templateFile; - } - - public void setTemplateFile(File templateFile) { - this.templateFile = templateFile; - } - - public Boolean getAutoCloseStream() { - return autoCloseStream; - } - - public void setAutoCloseStream(Boolean autoCloseStream) { - this.autoCloseStream = autoCloseStream; - } - - public Boolean getMandatoryUseInputStream() { - return mandatoryUseInputStream; - } - - public void setMandatoryUseInputStream(Boolean mandatoryUseInputStream) { - this.mandatoryUseInputStream = mandatoryUseInputStream; - } - - public Boolean getConvertAllFiled() { - return convertAllFiled; - } - - public void setConvertAllFiled(Boolean convertAllFiled) { - this.convertAllFiled = convertAllFiled; - } - - public com.alibaba.excel.event.WriteHandler getWriteHandler() { - return writeHandler; - } - - public void setWriteHandler(com.alibaba.excel.event.WriteHandler writeHandler) { - this.writeHandler = writeHandler; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Boolean getInMemory() { - return inMemory; - } - - public void setInMemory(Boolean inMemory) { - this.inMemory = inMemory; - } - - public Boolean getWriteExcelOnException() { - return writeExcelOnException; - } - - public void setWriteExcelOnException(Boolean writeExcelOnException) { - this.writeExcelOnException = writeExcelOnException; - } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java b/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java index 41b2cfc1..b9b377ed 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java +++ b/src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java @@ -4,11 +4,14 @@ import java.util.List; import com.alibaba.excel.enums.WriteTemplateAnalysisCellTypeEnum; +import lombok.Data; + /** * Read the cells of the template while populating the data. * * @author Jiaju Zhuang **/ +@Data public class AnalysisCell { private int columnIndex; private int rowIndex; @@ -19,70 +22,6 @@ public class AnalysisCell { private String prefix; private Boolean firstRow; - public int getColumnIndex() { - return columnIndex; - } - - public void setColumnIndex(int columnIndex) { - this.columnIndex = columnIndex; - } - - public int getRowIndex() { - return rowIndex; - } - - public void setRowIndex(int rowIndex) { - this.rowIndex = rowIndex; - } - - public List getVariableList() { - return variableList; - } - - public void setVariableList(List variableList) { - this.variableList = variableList; - } - - public List getPrepareDataList() { - return prepareDataList; - } - - public void setPrepareDataList(List prepareDataList) { - this.prepareDataList = prepareDataList; - } - - public Boolean getOnlyOneVariable() { - return onlyOneVariable; - } - - public void setOnlyOneVariable(Boolean onlyOneVariable) { - this.onlyOneVariable = onlyOneVariable; - } - - public String getPrefix() { - return prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public WriteTemplateAnalysisCellTypeEnum getCellType() { - return cellType; - } - - public void setCellType(WriteTemplateAnalysisCellTypeEnum cellType) { - this.cellType = cellType; - } - - public Boolean getFirstRow() { - return firstRow; - } - - public void setFirstRow(Boolean firstRow) { - this.firstRow = firstRow; - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java b/src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java index a5bbe917..8fdb240a 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java +++ b/src/main/java/com/alibaba/excel/write/metadata/fill/FillConfig.java @@ -2,11 +2,20 @@ package com.alibaba.excel.write.metadata.fill; import com.alibaba.excel.enums.WriteDirectionEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + /** * Fill config * * @author Jiaju Zhuang **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class FillConfig { private WriteDirectionEnum direction; /** @@ -16,23 +25,15 @@ public class FillConfig { * say the whole file will be stored in memory. */ private Boolean forceNewRow; - private boolean hasInit; - - public WriteDirectionEnum getDirection() { - return direction; - } - public void setDirection(WriteDirectionEnum direction) { - this.direction = direction; - } - - public Boolean getForceNewRow() { - return forceNewRow; - } + /** + * Automatically inherit style + * + * default true. + */ + private Boolean autoStyle; - public void setForceNewRow(Boolean forceNewRow) { - this.forceNewRow = forceNewRow; - } + private boolean hasInit; public void init() { if (hasInit) { @@ -44,40 +45,9 @@ public class FillConfig { if (forceNewRow == null) { forceNewRow = Boolean.FALSE; } - hasInit = true; - } - - public static FillConfigBuilder builder() { - return new FillConfigBuilder(); - } - - public static class FillConfigBuilder { - private FillConfig fillConfig; - - FillConfigBuilder() { - this.fillConfig = new FillConfig(); - } - - public FillConfigBuilder direction(WriteDirectionEnum direction) { - fillConfig.setDirection(direction); - return this; - } - - public FillConfigBuilder forceNewRow(Boolean forceNewRow) { - fillConfig.setForceNewRow(forceNewRow); - return this; + if (autoStyle == null) { + autoStyle = Boolean.TRUE; } - - public FillConfig build() { - return build(true); - } - - public FillConfig build(boolean autoInit) { - if (autoInit) { - fillConfig.init(); - } - return fillConfig; - } - + hasInit = true; } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java index 0fced0b5..2867bdc5 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java @@ -9,9 +9,6 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.IndexedColors; - import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; import com.alibaba.excel.converters.DefaultConverterLoader; @@ -19,13 +16,10 @@ import com.alibaba.excel.enums.HeadKindEnum; import com.alibaba.excel.event.NotRepeatExecutor; import com.alibaba.excel.event.Order; import com.alibaba.excel.metadata.AbstractHolder; -import com.alibaba.excel.metadata.Font; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.metadata.TableStyle; import com.alibaba.excel.metadata.property.LoopMergeProperty; import com.alibaba.excel.metadata.property.OnceAbsoluteMergeProperty; import com.alibaba.excel.metadata.property.RowHeightProperty; -import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.handler.DefaultWriteHandlerLoader; import com.alibaba.excel.write.handler.RowWriteHandler; @@ -35,21 +29,23 @@ import com.alibaba.excel.write.handler.WriteHandler; import com.alibaba.excel.write.merge.LoopMergeStrategy; import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.excel.write.metadata.WriteBasicParameter; -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.property.ExcelWriteHeadProperty; import com.alibaba.excel.write.style.AbstractVerticalCellStyleStrategy; -import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.column.AbstractHeadColumnWidthStyleStrategy; import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; + /** * Write holder configuration * * @author Jiaju Zhuang */ +@Data +@NoArgsConstructor public abstract class AbstractWriteHolder extends AbstractHolder implements WriteHolder { /** * Need Head @@ -87,7 +83,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ /** * Ignore the custom columns. */ - private Collection excludeColumnFiledNames; + private Collection excludeColumnFieldNames; /** * Only output the custom columns. */ @@ -95,21 +91,10 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ /** * Only output the custom columns. */ - private Collection includeColumnFiledNames; + private Collection includeColumnFieldNames; - public AbstractWriteHolder(WriteBasicParameter writeBasicParameter, AbstractWriteHolder parentAbstractWriteHolder, - Boolean convertAllFiled) { + public AbstractWriteHolder(WriteBasicParameter writeBasicParameter, AbstractWriteHolder parentAbstractWriteHolder) { super(writeBasicParameter, parentAbstractWriteHolder); - if (writeBasicParameter.getUse1904windowing() == null) { - if (parentAbstractWriteHolder == null) { - getGlobalConfiguration().setUse1904windowing(Boolean.FALSE); - } else { - getGlobalConfiguration() - .setUse1904windowing(parentAbstractWriteHolder.getGlobalConfiguration().getUse1904windowing()); - } - } else { - getGlobalConfiguration().setUse1904windowing(writeBasicParameter.getUse1904windowing()); - } if (writeBasicParameter.getUseScientificFormat() != null) { throw new UnsupportedOperationException("Currently does not support setting useScientificFormat."); @@ -155,20 +140,20 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ this.automaticMergeHead = writeBasicParameter.getAutomaticMergeHead(); } - if (writeBasicParameter.getExcludeColumnFiledNames() == null && parentAbstractWriteHolder != null) { - this.excludeColumnFiledNames = parentAbstractWriteHolder.getExcludeColumnFiledNames(); + if (writeBasicParameter.getExcludeColumnFieldNames() == null && parentAbstractWriteHolder != null) { + this.excludeColumnFieldNames = parentAbstractWriteHolder.getExcludeColumnFieldNames(); } else { - this.excludeColumnFiledNames = writeBasicParameter.getExcludeColumnFiledNames(); + this.excludeColumnFieldNames = writeBasicParameter.getExcludeColumnFieldNames(); } if (writeBasicParameter.getExcludeColumnIndexes() == null && parentAbstractWriteHolder != null) { this.excludeColumnIndexes = parentAbstractWriteHolder.getExcludeColumnIndexes(); } else { this.excludeColumnIndexes = writeBasicParameter.getExcludeColumnIndexes(); } - if (writeBasicParameter.getIncludeColumnFiledNames() == null && parentAbstractWriteHolder != null) { - this.includeColumnFiledNames = parentAbstractWriteHolder.getIncludeColumnFiledNames(); + if (writeBasicParameter.getIncludeColumnFieldNames() == null && parentAbstractWriteHolder != null) { + this.includeColumnFieldNames = parentAbstractWriteHolder.getIncludeColumnFieldNames(); } else { - this.includeColumnFiledNames = writeBasicParameter.getIncludeColumnFiledNames(); + this.includeColumnFieldNames = writeBasicParameter.getIncludeColumnFieldNames(); } if (writeBasicParameter.getIncludeColumnIndexes() == null && parentAbstractWriteHolder != null) { this.includeColumnIndexes = parentAbstractWriteHolder.getIncludeColumnIndexes(); @@ -177,10 +162,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ } // Initialization property - this.excelWriteHeadProperty = new ExcelWriteHeadProperty(this, getClazz(), getHead(), convertAllFiled); - - // Compatible with old code - compatibleOldCode(writeBasicParameter); + this.excelWriteHeadProperty = new ExcelWriteHeadProperty(this, getClazz(), getHead()); // Set writeHandlerMap List handlerList = new ArrayList(); @@ -207,7 +189,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ if (parentAbstractWriteHolder == null) { setConverterMap(DefaultConverterLoader.loadDefaultWriteConverter()); } else { - setConverterMap(new HashMap(parentAbstractWriteHolder.getConverterMap())); + setConverterMap(new HashMap<>(parentAbstractWriteHolder.getConverterMap())); } if (writeBasicParameter.getCustomConverterList() != null && !writeBasicParameter.getCustomConverterList().isEmpty()) { @@ -217,78 +199,6 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ } } - /** - * Compatible with old code - */ - @Deprecated - private void compatibleOldCode(WriteBasicParameter writeBasicParameter) { - switch (holderType()) { - case SHEET: - compatibleOldCodeCreateRowCellStyleStrategy(writeBasicParameter, - ((WriteSheet) writeBasicParameter).getTableStyle()); - compatibleOldCodeCreateHeadColumnWidthStyleStrategy(writeBasicParameter, - ((WriteSheet) writeBasicParameter).getColumnWidthMap()); - return; - case TABLE: - compatibleOldCodeCreateRowCellStyleStrategy(writeBasicParameter, - ((WriteTable) writeBasicParameter).getTableStyle()); - return; - default: - } - } - - @Deprecated - private void compatibleOldCodeCreateRowCellStyleStrategy(WriteBasicParameter writeBasicParameter, - TableStyle tableStyle) { - if (tableStyle == null) { - return; - } - if (writeBasicParameter.getCustomWriteHandlerList() == null) { - writeBasicParameter.setCustomWriteHandlerList(new ArrayList()); - } - writeBasicParameter.getCustomWriteHandlerList() - .add(new HorizontalCellStyleStrategy( - buildWriteCellStyle(tableStyle.getTableHeadFont(), tableStyle.getTableHeadBackGroundColor()), - buildWriteCellStyle(tableStyle.getTableContentFont(), tableStyle.getTableContentBackGroundColor()))); - } - - @Deprecated - private WriteCellStyle buildWriteCellStyle(Font font, IndexedColors indexedColors) { - WriteCellStyle writeCellStyle = new WriteCellStyle(); - if (indexedColors != null) { - writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); - writeCellStyle.setFillForegroundColor(indexedColors.getIndex()); - } - if (font != null) { - WriteFont writeFont = new WriteFont(); - writeFont.setFontName(font.getFontName()); - writeFont.setFontHeightInPoints(font.getFontHeightInPoints()); - writeFont.setBold(font.isBold()); - writeCellStyle.setWriteFont(writeFont); - } - return writeCellStyle; - } - - @Deprecated - private void compatibleOldCodeCreateHeadColumnWidthStyleStrategy(WriteBasicParameter writeBasicParameter, - final Map columnWidthMap) { - if (columnWidthMap == null || columnWidthMap.isEmpty()) { - return; - } - if (writeBasicParameter.getCustomWriteHandlerList() == null) { - writeBasicParameter.setCustomWriteHandlerList(new ArrayList()); - } - writeBasicParameter.getCustomWriteHandlerList().add(new AbstractHeadColumnWidthStyleStrategy() { - @Override - protected Integer columnWidth(Head head, Integer columnIndex) { - if (columnWidthMap.containsKey(head.getColumnIndex())) { - return columnWidthMap.get(head.getColumnIndex()) / 256; - } - return 20; - } - }); - } - protected void initAnnotationConfig(List handlerList, WriteBasicParameter writeBasicParameter) { if (!HeadKindEnum.CLASS.equals(getExcelWriteHeadProperty().getHeadKind())) { return; @@ -388,7 +298,6 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ handlerList.add(columnWidthStyleStrategy); } - protected Map, List> sortAndClearUpAllHandler( List handlerList, Map, List> parentHandlerMap) { // add @@ -408,7 +317,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ for (WriteHandler handler : handlerList) { int order = Integer.MIN_VALUE; if (handler instanceof Order) { - order = ((Order) handler).order(); + order = ((Order)handler).order(); } if (orderExcelWriteHandlerMap.containsKey(order)) { orderExcelWriteHandlerMap.get(order).add(handler); @@ -424,7 +333,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ for (Map.Entry> entry : orderExcelWriteHandlerMap.entrySet()) { for (WriteHandler handler : entry.getValue()) { if (handler instanceof NotRepeatExecutor) { - String uniqueValue = ((NotRepeatExecutor) handler).uniqueValue(); + String uniqueValue = ((NotRepeatExecutor)handler).uniqueValue(); if (alreadyExistedHandlerSet.contains(uniqueValue)) { continue; } @@ -462,10 +371,10 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ @Override public boolean ignore(String fieldName, Integer columnIndex) { if (fieldName != null) { - if (includeColumnFiledNames != null && !includeColumnFiledNames.contains(fieldName)) { + if (includeColumnFieldNames != null && !includeColumnFieldNames.contains(fieldName)) { return true; } - if (excludeColumnFiledNames != null && excludeColumnFiledNames.contains(fieldName)) { + if (excludeColumnFieldNames != null && excludeColumnFieldNames.contains(fieldName)) { return true; } } @@ -480,95 +389,6 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ return false; } - public Boolean getNeedHead() { - return needHead; - } - - public void setNeedHead(Boolean needHead) { - this.needHead = needHead; - } - - public Map, List> getWriteHandlerMap() { - return writeHandlerMap; - } - - public void setWriteHandlerMap(Map, List> writeHandlerMap) { - this.writeHandlerMap = writeHandlerMap; - } - - public Map, List> getOwnWriteHandlerMap() { - return ownWriteHandlerMap; - } - - public void setOwnWriteHandlerMap( - Map, List> ownWriteHandlerMap) { - this.ownWriteHandlerMap = ownWriteHandlerMap; - } - - public ExcelWriteHeadProperty getExcelWriteHeadProperty() { - return excelWriteHeadProperty; - } - - public void setExcelWriteHeadProperty(ExcelWriteHeadProperty excelWriteHeadProperty) { - this.excelWriteHeadProperty = excelWriteHeadProperty; - } - - public Integer getRelativeHeadRowIndex() { - return relativeHeadRowIndex; - } - - public void setRelativeHeadRowIndex(Integer relativeHeadRowIndex) { - this.relativeHeadRowIndex = relativeHeadRowIndex; - } - - public Boolean getUseDefaultStyle() { - return useDefaultStyle; - } - - public void setUseDefaultStyle(Boolean useDefaultStyle) { - this.useDefaultStyle = useDefaultStyle; - } - - public Boolean getAutomaticMergeHead() { - return automaticMergeHead; - } - - public void setAutomaticMergeHead(Boolean automaticMergeHead) { - this.automaticMergeHead = automaticMergeHead; - } - - public Collection getExcludeColumnIndexes() { - return excludeColumnIndexes; - } - - public void setExcludeColumnIndexes(Collection excludeColumnIndexes) { - this.excludeColumnIndexes = excludeColumnIndexes; - } - - public Collection getExcludeColumnFiledNames() { - return excludeColumnFiledNames; - } - - public void setExcludeColumnFiledNames(Collection excludeColumnFiledNames) { - this.excludeColumnFiledNames = excludeColumnFiledNames; - } - - public Collection getIncludeColumnIndexes() { - return includeColumnIndexes; - } - - public void setIncludeColumnIndexes(Collection includeColumnIndexes) { - this.includeColumnIndexes = includeColumnIndexes; - } - - public Collection getIncludeColumnFiledNames() { - return includeColumnFiledNames; - } - - public void setIncludeColumnFiledNames(Collection includeColumnFiledNames) { - this.includeColumnFiledNames = includeColumnFiledNames; - } - @Override public ExcelWriteHeadProperty excelWriteHeadProperty() { return getExcelWriteHeadProperty(); diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java index 56fc7e4e..580eeb97 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java @@ -3,21 +3,27 @@ package com.alibaba.excel.write.metadata.holder; import java.util.HashMap; import java.util.Map; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.xssf.streaming.SXSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFSheet; - import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.enums.WriteLastRowTypeEnum; import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.write.metadata.WriteSheet; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFSheet; + /** * sheet holder * * @author Jiaju Zhuang */ +@Data +@NoArgsConstructor public class WriteSheetHolder extends AbstractWriteHolder { /** * current param @@ -65,8 +71,13 @@ public class WriteSheetHolder extends AbstractWriteHolder { */ private WriteLastRowTypeEnum writeLastRowTypeEnum; + /** + * last row index + */ + private Integer lastRowIndex; + public WriteSheetHolder(WriteSheet writeSheet, WriteWorkbookHolder writeWorkbookHolder) { - super(writeSheet, writeWorkbookHolder, writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled()); + super(writeSheet, writeWorkbookHolder); this.writeSheet = writeSheet; if (writeSheet.getSheetNo() == null && StringUtils.isEmpty(writeSheet.getSheetName())) { this.sheetNo = 0; @@ -75,85 +86,22 @@ public class WriteSheetHolder extends AbstractWriteHolder { } this.sheetName = writeSheet.getSheetName(); this.parentWriteWorkbookHolder = writeWorkbookHolder; - this.hasBeenInitializedTable = new HashMap(); + this.hasBeenInitializedTable = new HashMap<>(); if (writeWorkbookHolder.getTempTemplateInputStream() != null) { writeLastRowTypeEnum = WriteLastRowTypeEnum.TEMPLATE_EMPTY; } else { writeLastRowTypeEnum = WriteLastRowTypeEnum.COMMON_EMPTY; } - } - - public WriteSheet getWriteSheet() { - return writeSheet; - } - - public void setWriteSheet(WriteSheet writeSheet) { - this.writeSheet = writeSheet; - } - - public Sheet getSheet() { - return sheet; - } - - public void setSheet(Sheet sheet) { - this.sheet = sheet; - } - - public Integer getSheetNo() { - return sheetNo; - } - - public Sheet getCachedSheet() { - return cachedSheet; - } - - public void setCachedSheet(Sheet cachedSheet) { - this.cachedSheet = cachedSheet; - } - - public void setSheetNo(Integer sheetNo) { - this.sheetNo = sheetNo; - } - - public String getSheetName() { - return sheetName; - } - - public void setSheetName(String sheetName) { - this.sheetName = sheetName; - } - - public WriteWorkbookHolder getParentWriteWorkbookHolder() { - return parentWriteWorkbookHolder; - } - - public void setParentWriteWorkbookHolder(WriteWorkbookHolder parentWriteWorkbookHolder) { - this.parentWriteWorkbookHolder = parentWriteWorkbookHolder; - } - - public Map getHasBeenInitializedTable() { - return hasBeenInitializedTable; - } - - public void setHasBeenInitializedTable(Map hasBeenInitializedTable) { - this.hasBeenInitializedTable = hasBeenInitializedTable; - } - - public WriteLastRowTypeEnum getWriteLastRowTypeEnum() { - return writeLastRowTypeEnum; - } - - public void setWriteLastRowTypeEnum(WriteLastRowTypeEnum writeLastRowTypeEnum) { - this.writeLastRowTypeEnum = writeLastRowTypeEnum; + lastRowIndex = 0; } /** - * Get the last line of index,you have to make sure that the data is written next + * Get the last line of index, you have to make sure that the data is written next * * @return */ public int getNewRowIndexAndStartDoWrite() { - // 'getLastRowNum' doesn't matter if it has one or zero,is's zero + // 'getLastRowNum' doesn't matter if it has one or zero, it's zero int newRowIndex = 0; switch (writeLastRowTypeEnum) { case TEMPLATE_EMPTY: diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteTableHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteTableHolder.java index f7242a2a..e353a44c 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteTableHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteTableHolder.java @@ -3,11 +3,14 @@ package com.alibaba.excel.write.metadata.holder; import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.write.metadata.WriteTable; +import lombok.Data; + /** * sheet holder * * @author Jiaju Zhuang */ +@Data public class WriteTableHolder extends AbstractWriteHolder { /*** * poi sheet @@ -22,38 +25,13 @@ public class WriteTableHolder extends AbstractWriteHolder { */ private WriteTable writeTable; - public WriteTableHolder(WriteTable writeTable, WriteSheetHolder writeSheetHolder, - WriteWorkbookHolder writeWorkbookHolder) { - super(writeTable, writeSheetHolder, writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled()); + public WriteTableHolder(WriteTable writeTable, WriteSheetHolder writeSheetHolder) { + super(writeTable, writeSheetHolder); this.parentWriteSheetHolder = writeSheetHolder; this.tableNo = writeTable.getTableNo(); this.writeTable = writeTable; } - public WriteSheetHolder getParentWriteSheetHolder() { - return parentWriteSheetHolder; - } - - public void setParentWriteSheetHolder(WriteSheetHolder parentWriteSheetHolder) { - this.parentWriteSheetHolder = parentWriteSheetHolder; - } - - public Integer getTableNo() { - return tableNo; - } - - public void setTableNo(Integer tableNo) { - this.tableNo = tableNo; - } - - public WriteTable getWriteTable() { - return writeTable; - } - - public void setWriteTable(WriteTable writeTable) { - this.writeTable = writeTable; - } - @Override public HolderEnum holderType() { return HolderEnum.TABLE; diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java index 8c84f1dc..85e15275 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java @@ -7,26 +7,36 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.exception.ExcelGenerateException; +import com.alibaba.excel.metadata.data.DataFormatData; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.IoUtils; +import com.alibaba.excel.util.MapUtils; +import com.alibaba.excel.util.StyleUtil; import com.alibaba.excel.write.metadata.WriteWorkbook; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; + +import lombok.Data; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * Workbook holder * * @author Jiaju Zhuang */ +@Data public class WriteWorkbookHolder extends AbstractWriteHolder { /*** * Current poi Workbook.This is only for writing, and there may be no data in version 07 when template data needs to @@ -52,23 +62,27 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { /** * Final output file *

- * If 'outputStream' and 'file' all not empty,file first + * If 'outputStream' and 'file' all not empty, file first */ private File file; /** * Final output stream */ private OutputStream outputStream; + /** + * output charset + */ + private Charset charset; /** * Template input stream *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private InputStream templateInputStream; /** * Template file *

- * If 'inputStream' and 'file' all not empty,file first + * If 'inputStream' and 'file' all not empty, file first */ private File templateFile; /** @@ -102,7 +116,7 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { */ private String password; /** - * Write excel in memory. Default false,the cache file is created and finally written to excel. + * Write excel in memory. Default false, the cache file is created and finally written to excel. *

* Comment and RichTextString are only supported in memory mode. */ @@ -112,9 +126,21 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { */ private Boolean writeExcelOnException; + /** + * Used to cell style. + */ + private Map cellStyleMap; + /** + * Used to font. + */ + private Map fontMap; + /** + * Used to data format. + */ + private Map dataFormatMap; public WriteWorkbookHolder(WriteWorkbook writeWorkbook) { - super(writeWorkbook, null, writeWorkbook.getConvertAllFiled()); + super(writeWorkbook, null); this.writeWorkbook = writeWorkbook; this.file = writeWorkbook.getFile(); if (file != null) { @@ -126,35 +152,49 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { } else { this.outputStream = writeWorkbook.getOutputStream(); } + + if (writeWorkbook.getCharset() == null) { + this.charset = Charset.defaultCharset(); + } else { + this.charset = writeWorkbook.getCharset(); + } + if (writeWorkbook.getAutoCloseStream() == null) { this.autoCloseStream = Boolean.TRUE; } else { this.autoCloseStream = writeWorkbook.getAutoCloseStream(); } - try { - copyTemplate(); - } catch (IOException e) { - throw new ExcelGenerateException("Copy template failure.", e); - } if (writeWorkbook.getExcelType() == null) { boolean isXls = (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue())) || (writeWorkbook.getTemplateFile() != null - && writeWorkbook.getTemplateFile().getName().endsWith(ExcelTypeEnum.XLS.getValue())); + && writeWorkbook.getTemplateFile().getName().endsWith(ExcelTypeEnum.XLS.getValue())); if (isXls) { this.excelType = ExcelTypeEnum.XLS; } else { - this.excelType = ExcelTypeEnum.XLSX; + boolean isCsv = (file != null && file.getName().endsWith(ExcelTypeEnum.CSV.getValue())) + || (writeWorkbook.getTemplateFile() != null + && writeWorkbook.getTemplateFile().getName().endsWith(ExcelTypeEnum.CSV.getValue())); + if (isCsv) { + this.excelType = ExcelTypeEnum.CSV; + } else { + this.excelType = ExcelTypeEnum.XLSX; + } } } else { this.excelType = writeWorkbook.getExcelType(); } + try { + copyTemplate(); + } catch (IOException e) { + throw new ExcelGenerateException("Copy template failure.", e); + } if (writeWorkbook.getMandatoryUseInputStream() == null) { this.mandatoryUseInputStream = Boolean.FALSE; } else { this.mandatoryUseInputStream = writeWorkbook.getMandatoryUseInputStream(); } - this.hasBeenInitializedSheetIndexMap = new HashMap(); - this.hasBeenInitializedSheetNameMap = new HashMap(); + this.hasBeenInitializedSheetIndexMap = new HashMap<>(); + this.hasBeenInitializedSheetNameMap = new HashMap<>(); this.password = writeWorkbook.getPassword(); if (writeWorkbook.getInMemory() == null) { this.inMemory = Boolean.FALSE; @@ -166,12 +206,18 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { } else { this.writeExcelOnException = writeWorkbook.getWriteExcelOnException(); } + this.cellStyleMap = MapUtils.newHashMap(); + this.fontMap = MapUtils.newHashMap(); + this.dataFormatMap = MapUtils.newHashMap(); } private void copyTemplate() throws IOException { if (writeWorkbook.getTemplateFile() == null && writeWorkbook.getTemplateInputStream() == null) { return; } + if (this.excelType == ExcelTypeEnum.CSV) { + throw new ExcelGenerateException("csv cannot use template."); + } byte[] templateFileByte = null; if (writeWorkbook.getTemplateFile() != null) { templateFileByte = FileUtils.readFileToByteArray(writeWorkbook.getTemplateFile()); @@ -187,136 +233,59 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { this.tempTemplateInputStream = new ByteArrayInputStream(templateFileByte); } - public Workbook getWorkbook() { - return workbook; - } - - public void setWorkbook(Workbook workbook) { - this.workbook = workbook; - } - - public Workbook getCachedWorkbook() { - return cachedWorkbook; - } - - public void setCachedWorkbook(Workbook cachedWorkbook) { - this.cachedWorkbook = cachedWorkbook; - } - - public Map getHasBeenInitializedSheetIndexMap() { - return hasBeenInitializedSheetIndexMap; - } - - public void setHasBeenInitializedSheetIndexMap(Map hasBeenInitializedSheetIndexMap) { - this.hasBeenInitializedSheetIndexMap = hasBeenInitializedSheetIndexMap; - } - - public Map getHasBeenInitializedSheetNameMap() { - return hasBeenInitializedSheetNameMap; - } - - public void setHasBeenInitializedSheetNameMap(Map hasBeenInitializedSheetNameMap) { - this.hasBeenInitializedSheetNameMap = hasBeenInitializedSheetNameMap; - } - - public WriteWorkbook getWriteWorkbook() { - return writeWorkbook; - } - - public void setWriteWorkbook(WriteWorkbook writeWorkbook) { - this.writeWorkbook = writeWorkbook; - } - - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - - public OutputStream getOutputStream() { - return outputStream; - } - - public void setOutputStream(OutputStream outputStream) { - this.outputStream = outputStream; - } - - public InputStream getTemplateInputStream() { - return templateInputStream; - } - - public void setTemplateInputStream(InputStream templateInputStream) { - this.templateInputStream = templateInputStream; - } - - public InputStream getTempTemplateInputStream() { - return tempTemplateInputStream; - } - - public void setTempTemplateInputStream(InputStream tempTemplateInputStream) { - this.tempTemplateInputStream = tempTemplateInputStream; - } - - public File getTemplateFile() { - return templateFile; - } - - public void setTemplateFile(File templateFile) { - this.templateFile = templateFile; - } - - public Boolean getAutoCloseStream() { - return autoCloseStream; - } - - public void setAutoCloseStream(Boolean autoCloseStream) { - this.autoCloseStream = autoCloseStream; - } - - public ExcelTypeEnum getExcelType() { - return excelType; - } - - public void setExcelType(ExcelTypeEnum excelType) { - this.excelType = excelType; - } - - public Boolean getMandatoryUseInputStream() { - return mandatoryUseInputStream; - } - - public void setMandatoryUseInputStream(Boolean mandatoryUseInputStream) { - this.mandatoryUseInputStream = mandatoryUseInputStream; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Boolean getInMemory() { - return inMemory; + @Override + public HolderEnum holderType() { + return HolderEnum.WORKBOOK; } - public void setInMemory(Boolean inMemory) { - this.inMemory = inMemory; + /** + * create a cell style. + * + * @param writeCellStyle + * @return + */ + public CellStyle createCellStyle(WriteCellStyle writeCellStyle) { + CellStyle cellStyle = cellStyleMap.get(writeCellStyle); + if (cellStyle != null) { + return cellStyle; + } + cellStyle = StyleUtil.buildCellStyle(workbook, writeCellStyle); + cellStyle.setDataFormat(createDataFormat(writeCellStyle.getDataFormatData())); + cellStyle.setFont(createFont(writeCellStyle.getWriteFont())); + cellStyleMap.put(writeCellStyle, cellStyle); + return cellStyle; } - public Boolean getWriteExcelOnException() { - return writeExcelOnException; + /** + * create a font. + * + * @param writeFont + * @return + */ + public Font createFont(WriteFont writeFont) { + Font font = fontMap.get(writeFont); + if (font != null) { + return font; + } + font = StyleUtil.buildFont(workbook, writeFont); + fontMap.put(writeFont, font); + return font; } - public void setWriteExcelOnException(Boolean writeExcelOnException) { - this.writeExcelOnException = writeExcelOnException; + /** + * create a data format. + * + * @param dataFormatData + * @return + */ + public Short createDataFormat(DataFormatData dataFormatData) { + Short dataFormat = dataFormatMap.get(dataFormatData); + if (dataFormat != null) { + return dataFormat; + } + dataFormat = StyleUtil.buildDataFormat(workbook, dataFormatData); + dataFormatMap.put(dataFormatData, dataFormat); + return dataFormat; } - @Override - public HolderEnum holderType() { - return HolderEnum.WORKBOOK; - } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/style/WriteCellStyle.java b/src/main/java/com/alibaba/excel/write/metadata/style/WriteCellStyle.java index 81c85e83..4b76805b 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/style/WriteCellStyle.java +++ b/src/main/java/com/alibaba/excel/write/metadata/style/WriteCellStyle.java @@ -1,27 +1,31 @@ package com.alibaba.excel.write.metadata.style; +import com.alibaba.excel.constant.BuiltinFormats; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.property.FontProperty; +import com.alibaba.excel.metadata.property.StyleProperty; +import com.alibaba.excel.util.StringUtils; + +import lombok.Data; import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.IgnoredErrorType; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.VerticalAlignment; -import com.alibaba.excel.metadata.property.FontProperty; -import com.alibaba.excel.metadata.property.StyleProperty; -import com.alibaba.excel.util.StringUtils; - /** * Cell style when writing * * @author Jiaju Zhuang */ +@Data public class WriteCellStyle { /** * Set the data format (must be a valid format). Built in formats are defined at {@link BuiltinFormats}. */ - private Short dataFormat; + private DataFormatData dataFormatData; + /** * Set the font for this style */ @@ -48,7 +52,6 @@ public class WriteCellStyle { /** * Set whether the text should be wrapped. Setting this flag to true make all content visible within a * cell by displaying it on multiple lines - * */ private Boolean wrapped; /** @@ -96,7 +99,6 @@ public class WriteCellStyle { * Set the color to use for the right border * * @see IndexedColors - * */ private Short rightBorderColor; @@ -104,14 +106,12 @@ public class WriteCellStyle { * Set the color to use for the top border * * @see IndexedColors - * */ private Short topBorderColor; /** * Set the color to use for the bottom border * * @see IndexedColors - * */ private Short bottomBorderColor; /** @@ -125,7 +125,6 @@ public class WriteCellStyle { * Set the background fill color. * * @see IndexedColors - * */ private Short fillBackgroundColor; @@ -133,7 +132,6 @@ public class WriteCellStyle { * Set the foreground fill color Note: Ensure Foreground color is set prior to background color. * * @see IndexedColors - * */ private Short fillForegroundColor; /** @@ -147,9 +145,7 @@ public class WriteCellStyle { } WriteCellStyle writeCellStyle = new WriteCellStyle(); if (styleProperty != null) { - if (styleProperty.getDataFormat() >= 0) { - writeCellStyle.setDataFormat(styleProperty.getDataFormat()); - } + writeCellStyle.setDataFormatData(styleProperty.getDataFormatData()); writeCellStyle.setHidden(styleProperty.getHidden()); writeCellStyle.setLocked(styleProperty.getLocked()); writeCellStyle.setQuotePrefix(styleProperty.getQuotePrefix()); @@ -213,180 +209,4 @@ public class WriteCellStyle { return writeCellStyle; } - - public Short getDataFormat() { - return dataFormat; - } - - public void setDataFormat(Short dataFormat) { - this.dataFormat = dataFormat; - } - - public WriteFont getWriteFont() { - return writeFont; - } - - public void setWriteFont(WriteFont writeFont) { - this.writeFont = writeFont; - } - - public Boolean getHidden() { - return hidden; - } - - public void setHidden(Boolean hidden) { - this.hidden = hidden; - } - - public Boolean getLocked() { - return locked; - } - - public void setLocked(Boolean locked) { - this.locked = locked; - } - - public Boolean getQuotePrefix() { - return quotePrefix; - } - - public void setQuotePrefix(Boolean quotePrefix) { - this.quotePrefix = quotePrefix; - } - - public HorizontalAlignment getHorizontalAlignment() { - return horizontalAlignment; - } - - public void setHorizontalAlignment(HorizontalAlignment horizontalAlignment) { - this.horizontalAlignment = horizontalAlignment; - } - - public Boolean getWrapped() { - return wrapped; - } - - public void setWrapped(Boolean wrapped) { - this.wrapped = wrapped; - } - - public VerticalAlignment getVerticalAlignment() { - return verticalAlignment; - } - - public void setVerticalAlignment(VerticalAlignment verticalAlignment) { - this.verticalAlignment = verticalAlignment; - } - - public Short getRotation() { - return rotation; - } - - public void setRotation(Short rotation) { - this.rotation = rotation; - } - - public Short getIndent() { - return indent; - } - - public void setIndent(Short indent) { - this.indent = indent; - } - - public BorderStyle getBorderLeft() { - return borderLeft; - } - - public void setBorderLeft(BorderStyle borderLeft) { - this.borderLeft = borderLeft; - } - - public BorderStyle getBorderRight() { - return borderRight; - } - - public void setBorderRight(BorderStyle borderRight) { - this.borderRight = borderRight; - } - - public BorderStyle getBorderTop() { - return borderTop; - } - - public void setBorderTop(BorderStyle borderTop) { - this.borderTop = borderTop; - } - - public BorderStyle getBorderBottom() { - return borderBottom; - } - - public void setBorderBottom(BorderStyle borderBottom) { - this.borderBottom = borderBottom; - } - - public Short getLeftBorderColor() { - return leftBorderColor; - } - - public void setLeftBorderColor(Short leftBorderColor) { - this.leftBorderColor = leftBorderColor; - } - - public Short getRightBorderColor() { - return rightBorderColor; - } - - public void setRightBorderColor(Short rightBorderColor) { - this.rightBorderColor = rightBorderColor; - } - - public Short getTopBorderColor() { - return topBorderColor; - } - - public void setTopBorderColor(Short topBorderColor) { - this.topBorderColor = topBorderColor; - } - - public Short getBottomBorderColor() { - return bottomBorderColor; - } - - public void setBottomBorderColor(Short bottomBorderColor) { - this.bottomBorderColor = bottomBorderColor; - } - - public FillPatternType getFillPatternType() { - return fillPatternType; - } - - public void setFillPatternType(FillPatternType fillPatternType) { - this.fillPatternType = fillPatternType; - } - - public Short getFillBackgroundColor() { - return fillBackgroundColor; - } - - public void setFillBackgroundColor(Short fillBackgroundColor) { - this.fillBackgroundColor = fillBackgroundColor; - } - - public Short getFillForegroundColor() { - return fillForegroundColor; - } - - public void setFillForegroundColor(Short fillForegroundColor) { - this.fillForegroundColor = fillForegroundColor; - } - - public Boolean getShrinkToFit() { - return shrinkToFit; - } - - public void setShrinkToFit(Boolean shrinkToFit) { - this.shrinkToFit = shrinkToFit; - } } diff --git a/src/main/java/com/alibaba/excel/write/metadata/style/WriteFont.java b/src/main/java/com/alibaba/excel/write/metadata/style/WriteFont.java index 6ed4c2a7..f7194bf9 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/style/WriteFont.java +++ b/src/main/java/com/alibaba/excel/write/metadata/style/WriteFont.java @@ -1,5 +1,6 @@ package com.alibaba.excel.write.metadata.style; +import lombok.Data; import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.ss.usermodel.Font; @@ -10,6 +11,7 @@ import org.apache.poi.ss.usermodel.IndexedColors; * * @author jipengfei */ +@Data public class WriteFont { /** * The name for the font (i.e. Arial) @@ -37,7 +39,7 @@ public class WriteFont { */ private Short color; /** - * Set normal,super or subscript. + * Set normal, super or subscript. * * @see Font#SS_NONE * @see Font#SS_SUPER @@ -68,76 +70,4 @@ public class WriteFont { * Bold */ private Boolean bold; - - public String getFontName() { - return fontName; - } - - public void setFontName(String fontName) { - this.fontName = fontName; - } - - public Short getFontHeightInPoints() { - return fontHeightInPoints; - } - - public void setFontHeightInPoints(Short fontHeightInPoints) { - this.fontHeightInPoints = fontHeightInPoints; - } - - public Boolean getItalic() { - return italic; - } - - public void setItalic(Boolean italic) { - this.italic = italic; - } - - public Boolean getStrikeout() { - return strikeout; - } - - public void setStrikeout(Boolean strikeout) { - this.strikeout = strikeout; - } - - public Short getColor() { - return color; - } - - public void setColor(Short color) { - this.color = color; - } - - public Short getTypeOffset() { - return typeOffset; - } - - public void setTypeOffset(Short typeOffset) { - this.typeOffset = typeOffset; - } - - public Byte getUnderline() { - return underline; - } - - public void setUnderline(Byte underline) { - this.underline = underline; - } - - public Integer getCharset() { - return charset; - } - - public void setCharset(Integer charset) { - this.charset = charset; - } - - public Boolean getBold() { - return bold; - } - - public void setBold(Boolean bold) { - this.bold = bold; - } } diff --git a/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java b/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java index 979a7750..c2779136 100644 --- a/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java +++ b/src/main/java/com/alibaba/excel/write/property/ExcelWriteHeadProperty.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import com.alibaba.excel.annotation.format.NumberFormat; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentFontStyle; import com.alibaba.excel.annotation.write.style.ContentLoopMerge; @@ -17,9 +16,6 @@ import com.alibaba.excel.annotation.write.style.HeadFontStyle; import com.alibaba.excel.annotation.write.style.HeadRowHeight; import com.alibaba.excel.annotation.write.style.HeadStyle; import com.alibaba.excel.annotation.write.style.OnceAbsoluteMerge; -import com.alibaba.excel.converters.ConverterKeyBuild; -import com.alibaba.excel.converters.DefaultConverterLoader; -import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.enums.HeadKindEnum; import com.alibaba.excel.metadata.CellRange; import com.alibaba.excel.metadata.Head; @@ -44,23 +40,23 @@ public class ExcelWriteHeadProperty extends ExcelHeadProperty { private RowHeightProperty contentRowHeightProperty; private OnceAbsoluteMergeProperty onceAbsoluteMergeProperty; - public ExcelWriteHeadProperty(Holder holder, Class headClazz, List> head, Boolean convertAllFiled) { - super(holder, headClazz, head, convertAllFiled); + public ExcelWriteHeadProperty(Holder holder, Class headClazz, List> head) { + super(holder, headClazz, head); if (getHeadKind() != HeadKindEnum.CLASS) { return; } this.headRowHeightProperty = - RowHeightProperty.build((HeadRowHeight) headClazz.getAnnotation(HeadRowHeight.class)); + RowHeightProperty.build((HeadRowHeight)headClazz.getAnnotation(HeadRowHeight.class)); this.contentRowHeightProperty = - RowHeightProperty.build((ContentRowHeight) headClazz.getAnnotation(ContentRowHeight.class)); + RowHeightProperty.build((ContentRowHeight)headClazz.getAnnotation(ContentRowHeight.class)); this.onceAbsoluteMergeProperty = - OnceAbsoluteMergeProperty.build((OnceAbsoluteMerge) headClazz.getAnnotation(OnceAbsoluteMerge.class)); + OnceAbsoluteMergeProperty.build((OnceAbsoluteMerge)headClazz.getAnnotation(OnceAbsoluteMerge.class)); - ColumnWidth parentColumnWidth = (ColumnWidth) headClazz.getAnnotation(ColumnWidth.class); - HeadStyle parentHeadStyle = (HeadStyle) headClazz.getAnnotation(HeadStyle.class); - HeadFontStyle parentHeadFontStyle = (HeadFontStyle) headClazz.getAnnotation(HeadFontStyle.class); - ContentStyle parentContentStyle = (ContentStyle) headClazz.getAnnotation(ContentStyle.class); - ContentFontStyle parentContentFontStyle = (ContentFontStyle) headClazz.getAnnotation(ContentFontStyle.class); + ColumnWidth parentColumnWidth = (ColumnWidth)headClazz.getAnnotation(ColumnWidth.class); + HeadStyle parentHeadStyle = (HeadStyle)headClazz.getAnnotation(HeadStyle.class); + HeadFontStyle parentHeadFontStyle = (HeadFontStyle)headClazz.getAnnotation(HeadFontStyle.class); + ContentStyle parentContentStyle = (ContentStyle)headClazz.getAnnotation(ContentStyle.class); + ContentFontStyle parentContentFontStyle = (ContentFontStyle)headClazz.getAnnotation(ContentFontStyle.class); for (Map.Entry entry : getContentPropertyMap().entrySet()) { Integer index = entry.getKey(); @@ -102,14 +98,6 @@ public class ExcelWriteHeadProperty extends ExcelHeadProperty { headData.setContentFontProperty(FontProperty.build(contentFontStyle)); headData.setLoopMergeProperty(LoopMergeProperty.build(field.getAnnotation(ContentLoopMerge.class))); - // If have @NumberFormat, 'NumberStringConverter' is specified by default - if (excelContentPropertyData.getConverter() == null) { - NumberFormat numberFormat = field.getAnnotation(NumberFormat.class); - if (numberFormat != null) { - excelContentPropertyData.setConverter(DefaultConverterLoader.loadAllConverter() - .get(ConverterKeyBuild.buildKey(field.getType(), CellDataTypeEnum.STRING))); - } - } } } @@ -158,18 +146,21 @@ public class ExcelWriteHeadProperty extends ExcelHeadProperty { int lastCol = i; int lastRow = j; for (int k = i + 1; k < headList.size(); k++) { - if (headList.get(k).getHeadNameList().get(j).equals(headName)) { - alreadyRangeSet.add(k + "-" + j); + String key = k + "-" + j; + if (headList.get(k).getHeadNameList().get(j).equals(headName) && !alreadyRangeSet.contains(key)) { + alreadyRangeSet.add(key); lastCol = k; } else { break; } } - Set tempAlreadyRangeSet = new HashSet(); + Set tempAlreadyRangeSet = new HashSet<>(); outer: for (int k = j + 1; k < headNameList.size(); k++) { for (int l = i; l <= lastCol; l++) { - if (headList.get(l).getHeadNameList().get(k).equals(headName)) { + String key = l + "-" + k; + if (headList.get(l).getHeadNameList().get(k).equals(headName) && !alreadyRangeSet.contains( + key)) { tempAlreadyRangeSet.add(l + "-" + k); } else { break outer; diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java index 14ad9ce5..9a918b27 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java @@ -1,88 +1,44 @@ package com.alibaba.excel.write.style; -import java.util.List; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Workbook; - -import com.alibaba.excel.event.NotRepeatExecutor; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.constant.OrderConstant; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; -import com.alibaba.excel.write.handler.SheetWriteHandler; -import com.alibaba.excel.write.handler.WorkbookWriteHandler; -import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteTableHolder; -import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; + +import org.apache.poi.ss.usermodel.Cell; /** * Cell style strategy * * @author Jiaju Zhuang */ -public abstract class AbstractCellStyleStrategy implements CellWriteHandler, WorkbookWriteHandler, NotRepeatExecutor { - - boolean hasInitialized = false; - - @Override - public String uniqueValue() { - return "CellStyleStrategy"; - } - - @Override - public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { - - } - - @Override - public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, - Head head, Integer relativeRowIndex, Boolean isHead) { - - } +public abstract class AbstractCellStyleStrategy implements CellWriteHandler { @Override - public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { - + public int order() { + return OrderConstant.DEFINE_STYLE; } @Override - public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { - if (isHead == null) { + public void afterCellDispose(CellWriteHandlerContext context) { + if (context.getHead() == null) { return; } - if (isHead) { - setHeadCellStyle(cell, head, relativeRowIndex); + if (context.getHead()) { + setHeadCellStyle(context); } else { - setContentCellStyle(cell, head, relativeRowIndex); + setContentCellStyle(context); } } - @Override - public void beforeWorkbookCreate() { - - } - - @Override - public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) { - initCellStyle(writeWorkbookHolder.getWorkbook()); - hasInitialized = true; - } - - @Override - public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) { - - } - /** - * Initialization cell style + * Sets the cell style of header * - * @param workbook + * @param context */ - protected abstract void initCellStyle(Workbook workbook); + protected void setHeadCellStyle(CellWriteHandlerContext context) { + setHeadCellStyle(context.getCell(), context.getHeadData(), context.getRelativeRowIndex()); + } /** * Sets the cell style of header @@ -91,7 +47,18 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, Wor * @param head * @param relativeRowIndex */ - protected abstract void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex); + protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) { + throw new UnsupportedOperationException("Custom styles must override the setHeadCellStyle method."); + } + + /** + * Sets the cell style of content + * + * @param context + */ + protected void setContentCellStyle(CellWriteHandlerContext context) { + setContentCellStyle(context.getCell(), context.getHeadData(), context.getRelativeRowIndex()); + } /** * Sets the cell style of content @@ -100,6 +67,8 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, Wor * @param head * @param relativeRowIndex */ - protected abstract void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex); + protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) { + throw new UnsupportedOperationException("Custom styles must override the setContentCellStyle method."); + } } diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java index 197c5cf8..7d8e1b46 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java @@ -1,16 +1,14 @@ package com.alibaba.excel.write.style; -import java.util.HashMap; -import java.util.Map; - -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.Workbook; +import java.util.List; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import org.apache.commons.collections4.CollectionUtils; + /** * Use the same style for the column * @@ -18,59 +16,32 @@ import com.alibaba.excel.write.metadata.style.WriteCellStyle; */ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyleStrategy { - private Workbook workbook; - private Map headCellStyleCache = new HashMap(); - private Map contentCellStyleCache = new HashMap(); - - @Override - protected void initCellStyle(Workbook workbook) { - this.workbook = workbook; - } - @Override - protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) { - if (head == null) { + protected void setHeadCellStyle(CellWriteHandlerContext context) { + if (stopProcessing(context)) { return; } - int columnIndex = head.getColumnIndex(); - if (headCellStyleCache.containsKey(columnIndex)) { - CellStyle cellStyle = headCellStyleCache.get(columnIndex); - if (cellStyle != null) { - cell.setCellStyle(cellStyle); - } - return; - } - WriteCellStyle headCellStyle = headCellStyle(head); - if (headCellStyle == null) { - headCellStyleCache.put(columnIndex, null); - } else { - CellStyle cellStyle = StyleUtil.buildHeadCellStyle(workbook, headCellStyle); - headCellStyleCache.put(columnIndex, cellStyle); - cell.setCellStyle(cellStyle); - } + WriteCellData cellData = context.getCellDataList().get(0); + cellData.setWriteCellStyle(headCellStyle(context.getHeadData())); } @Override - protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) { - if (head == null) { - return; - } - int columnIndex = head.getColumnIndex(); - if (contentCellStyleCache.containsKey(columnIndex)) { - CellStyle cellStyle = contentCellStyleCache.get(columnIndex); - if (cellStyle != null) { - cell.setCellStyle(cellStyle); - } + protected void setContentCellStyle(CellWriteHandlerContext context) { + if (stopProcessing(context)) { return; } - WriteCellStyle contentCellStyle = contentCellStyle(head); - if (contentCellStyle == null) { - contentCellStyleCache.put(columnIndex, null); - } else { - CellStyle cellStyle = StyleUtil.buildContentCellStyle(workbook, contentCellStyle); - contentCellStyleCache.put(columnIndex, cellStyle); - cell.setCellStyle(cellStyle); - } + WriteCellData cellData = context.getCellDataList().get(0); + cellData.setWriteCellStyle(contentCellStyle(context)); + } + + /** + * Returns the column width corresponding to each column head. + * + * @param context + * @return + */ + protected WriteCellStyle contentCellStyle(CellWriteHandlerContext context) { + return contentCellStyle(context.getHeadData()); } /** @@ -87,6 +58,17 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl * @param head Nullable * @return */ - protected abstract WriteCellStyle contentCellStyle(Head head); + protected WriteCellStyle contentCellStyle(Head head) { + throw new UnsupportedOperationException( + "One of the two methods 'contentCellStyle(Cell cell, Head head, Integer relativeRowIndex)' and " + + "'contentCellStyle(Head head)' must be implemented."); + } + protected boolean stopProcessing(CellWriteHandlerContext context) { + List> cellDataList = context.getCellDataList(); + if (CollectionUtils.isEmpty(cellDataList) || cellDataList.size() > 1) { + return true; + } + return context.getHeadData() == null; + } } diff --git a/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java index 295cd556..58b0836a 100644 --- a/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java @@ -1,18 +1,15 @@ package com.alibaba.excel.write.style; -import java.util.ArrayList; import java.util.List; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.Workbook; - -import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import org.apache.commons.collections4.CollectionUtils; + /** - * * Use the same style for the row * * @author Jiaju Zhuang @@ -22,9 +19,6 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { private WriteCellStyle headWriteCellStyle; private List contentWriteCellStyleList; - private CellStyle headCellStyle; - private List contentCellStyleList; - public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle, List contentWriteCellStyleList) { this.headWriteCellStyle = headWriteCellStyle; @@ -33,37 +27,37 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle, WriteCellStyle contentWriteCellStyle) { this.headWriteCellStyle = headWriteCellStyle; - contentWriteCellStyleList = new ArrayList(); - contentWriteCellStyleList.add(contentWriteCellStyle); - } - - @Override - protected void initCellStyle(Workbook workbook) { - if (headWriteCellStyle != null) { - headCellStyle = StyleUtil.buildHeadCellStyle(workbook, headWriteCellStyle); - } - if (contentWriteCellStyleList != null && !contentWriteCellStyleList.isEmpty()) { - contentCellStyleList = new ArrayList(); - for (WriteCellStyle writeCellStyle : contentWriteCellStyleList) { - contentCellStyleList.add(StyleUtil.buildContentCellStyle(workbook, writeCellStyle)); - } + if (contentWriteCellStyle != null) { + this.contentWriteCellStyleList = ListUtils.newArrayList(contentWriteCellStyle); } } @Override - protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) { - if (headCellStyle == null) { + protected void setHeadCellStyle(CellWriteHandlerContext context) { + if (stopProcessing(context) || headWriteCellStyle == null) { return; } - cell.setCellStyle(headCellStyle); + WriteCellData cellData = context.getCellDataList().get(0); + cellData.setWriteCellStyle(headWriteCellStyle); } @Override - protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) { - if (contentCellStyleList == null || contentCellStyleList.isEmpty()) { + protected void setContentCellStyle(CellWriteHandlerContext context) { + if (stopProcessing(context) || CollectionUtils.isEmpty(contentWriteCellStyleList)) { return; } - cell.setCellStyle(contentCellStyleList.get(relativeRowIndex % contentCellStyleList.size())); + WriteCellData cellData = context.getCellDataList().get(0); + if (context.getRelativeRowIndex() == null || context.getRelativeRowIndex() <= 0) { + cellData.setWriteCellStyle(contentWriteCellStyleList.get(0)); + } else { + cellData.setWriteCellStyle( + contentWriteCellStyleList.get(context.getRelativeRowIndex() % contentWriteCellStyleList.size())); + } + } + + protected boolean stopProcessing(CellWriteHandlerContext context) { + List> cellDataList = context.getCellDataList(); + return CollectionUtils.isEmpty(cellDataList) || cellDataList.size() > 1; } } diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java index 005f624e..e33f74e0 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java @@ -2,31 +2,34 @@ package com.alibaba.excel.write.style.column; import java.util.List; -import org.apache.poi.ss.usermodel.Cell; - -import com.alibaba.excel.event.NotRepeatExecutor; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.write.handler.AbstractCellWriteHandler; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteTableHolder; + +import org.apache.poi.ss.usermodel.Cell; /** * Column width style strategy * * @author Jiaju Zhuang */ -public abstract class AbstractColumnWidthStyleStrategy extends AbstractCellWriteHandler implements NotRepeatExecutor { +public abstract class AbstractColumnWidthStyleStrategy implements CellWriteHandler { @Override - public String uniqueValue() { - return "ColumnWidthStyleStrategy"; + public void afterCellDispose(CellWriteHandlerContext context) { + setColumnWidth(context); } - @Override - public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { - setColumnWidth(writeSheetHolder, cellDataList, cell, head, relativeRowIndex, isHead); + /** + * Sets the column width when head create + * + * @param context + */ + protected void setColumnWidth(CellWriteHandlerContext context) { + setColumnWidth(context.getWriteSheetHolder(), context.getCellDataList(), context.getCell(), + context.getHeadData(), context.getRelativeRowIndex(), context.getHead()); } /** @@ -39,7 +42,9 @@ public abstract class AbstractColumnWidthStyleStrategy extends AbstractCellWrite * @param relativeRowIndex * @param isHead */ - protected abstract void setColumnWidth(WriteSheetHolder writeSheetHolder, List cellDataList, Cell cell, - Head head, Integer relativeRowIndex, Boolean isHead); + protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List> cellDataList, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { + throw new UnsupportedOperationException("Custom styles must override the setColumnWidth method."); + } } diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java index 1a88eff6..60a6cfc0 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java @@ -2,12 +2,12 @@ package com.alibaba.excel.write.style.column; import java.util.List; -import org.apache.poi.ss.usermodel.Cell; - -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import org.apache.poi.ss.usermodel.Cell; + /** * Returns the column width according to each column header * @@ -16,7 +16,7 @@ import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy { @Override - protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List cellDataList, Cell cell, Head head, + protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { boolean needSetWidth = relativeRowIndex != null && (isHead || relativeRowIndex == 0); if (!needSetWidth) { @@ -33,7 +33,7 @@ public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColum * Returns the column width corresponding to each column head. * *

- * if return null,ignore + * if return null, ignore * * @param head * Nullable. diff --git a/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java index cc8dcb20..d248de13 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/LongestMatchColumnWidthStyleStrategy.java @@ -4,14 +4,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.poi.ss.usermodel.Cell; - import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.util.CollectionUtils; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.util.MapUtils; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.ss.usermodel.Cell; + /** * Take the width of the longest column as the width. *

@@ -24,10 +25,11 @@ public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthSty private static final int MAX_COLUMN_WIDTH = 255; - private Map> cache = new HashMap>(8); + private final Map> cache = MapUtils.newHashMapWithExpectedSize(8); @Override - protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List cellDataList, Cell cell, Head head, + protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List> cellDataList, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList); if (!needSetWidth) { @@ -52,11 +54,11 @@ public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthSty } } - private Integer dataLength(List cellDataList, Cell cell, Boolean isHead) { + private Integer dataLength(List> cellDataList, Cell cell, Boolean isHead) { if (isHead) { return cell.getStringCellValue().getBytes().length; } - CellData cellData = cellDataList.get(0); + WriteCellData cellData = cellDataList.get(0); CellDataTypeEnum type = cellData.getType(); if (type == null) { return -1; diff --git a/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java index 303c8180..6c908eb6 100644 --- a/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHeightStyleStrategy.java @@ -1,46 +1,25 @@ package com.alibaba.excel.write.style.row; -import org.apache.poi.ss.usermodel.Row; - -import com.alibaba.excel.event.NotRepeatExecutor; import com.alibaba.excel.write.handler.RowWriteHandler; -import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import com.alibaba.excel.write.handler.context.RowWriteHandlerContext; + +import org.apache.poi.ss.usermodel.Row; /** * Set the row height strategy * * @author Jiaju Zhuang */ -public abstract class AbstractRowHeightStyleStrategy implements RowWriteHandler, NotRepeatExecutor { - - @Override - public String uniqueValue() { - return "RowHighStyleStrategy"; - } - - @Override - public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, - Integer relativeRowIndex, Boolean isHead) { - - } - - @Override - public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Integer relativeRowIndex, Boolean isHead) { - - } - +public abstract class AbstractRowHeightStyleStrategy implements RowWriteHandler { @Override - public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, - Integer relativeRowIndex, Boolean isHead) { - if (isHead == null) { + public void afterRowDispose(RowWriteHandlerContext context) { + if (context.getHead() == null) { return; } - if (isHead) { - setHeadColumnHeight(row, relativeRowIndex); + if (context.getHead()) { + setHeadColumnHeight(context.getRow(), context.getRelativeRowIndex()); } else { - setContentColumnHeight(row, relativeRowIndex); + setContentColumnHeight(context.getRow(), context.getRelativeRowIndex()); } } diff --git a/src/main/java/org/apache/poi/hssf/usermodel/PoiUtils.java b/src/main/java/org/apache/poi/hssf/usermodel/PoiUtils.java new file mode 100644 index 00000000..4f1d404f --- /dev/null +++ b/src/main/java/org/apache/poi/hssf/usermodel/PoiUtils.java @@ -0,0 +1,37 @@ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.util.BitField; +import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.xssf.usermodel.XSSFRow; + +/** + * utils + * + * @author Jiaju Zhuang + */ +public class PoiUtils { + + /** + * Whether to customize the height + */ + public static final BitField CUSTOM_HEIGHT = BitFieldFactory.getInstance(0x640); + + /** + * Whether to customize the height + * + * @param row row + * @return + */ + public static boolean customHeight(Row row) { + if (row instanceof XSSFRow) { + XSSFRow xssfRow = (XSSFRow)row; + return xssfRow.getCTRow().getCustomHeight(); + } + if (row instanceof HSSFRow) { + HSSFRow hssfRow = (HSSFRow)row; + return CUSTOM_HEIGHT.getValue(hssfRow.getRowRecord().getOptionFlags()) == 1; + } + return false; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationData.java b/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationData.java index f1e91197..d1c2a4f7 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationData.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationData.java @@ -9,7 +9,6 @@ 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.converters.doubleconverter.DoubleStringConverter; import lombok.Data; @@ -24,7 +23,7 @@ public class AnnotationData { @ExcelProperty("日期") @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒") private Date date; - @ExcelProperty(value = "数字", converter = DoubleStringConverter.class) + @ExcelProperty(value = "数字") @NumberFormat("#.##%") private Double number; @ExcelIgnore diff --git a/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java index 4489f1c1..7a4dfe21 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java @@ -4,26 +4,27 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.Test; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.util.DateUtils; +import org.junit.BeforeClass; +import org.junit.Test; + /** - * * @author Jiaju Zhuang */ public class AnnotationDataTest { private static File file07; private static File file03; + private static File fileCsv; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("annotation07.xlsx"); file03 = TestFileUtil.createNewFile("annotation03.xls"); + fileCsv = TestFileUtil.createNewFile("annotationCsv.csv"); } @Test @@ -36,6 +37,11 @@ public class AnnotationDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() throws Exception { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) throws Exception { EasyExcel.write().file(file).head(AnnotationData.class).sheet().doWrite(data()); EasyExcel.read().file(file).head(AnnotationData.class).registerReadListener(new AnnotationDataListener()) @@ -43,7 +49,7 @@ public class AnnotationDataTest { } private List data() throws Exception { - List list = new ArrayList(); + List list = new ArrayList<>(); AnnotationData data = new AnnotationData(); data.setDate(DateUtils.parseDate("2020-01-01 01:01:01")); data.setNumber(99.99); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationIndexAndNameDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationIndexAndNameDataTest.java index cd069c81..937cf665 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationIndexAndNameDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationIndexAndNameDataTest.java @@ -4,12 +4,12 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.Test; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import org.junit.BeforeClass; +import org.junit.Test; + /** * Annotation data test * @@ -19,11 +19,13 @@ public class AnnotationIndexAndNameDataTest { private static File file07; private static File file03; + private static File fileCsv; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("annotationIndexAndName07.xlsx"); file03 = TestFileUtil.createNewFile("annotationIndexAndName03.xls"); + fileCsv = TestFileUtil.createNewFile("annotationIndexAndNameCsv.csv"); } @Test @@ -36,6 +38,11 @@ public class AnnotationIndexAndNameDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) { EasyExcel.write(file, AnnotationIndexAndNameData.class).sheet().doWrite(data()); EasyExcel.read(file, AnnotationIndexAndNameData.class, new AnnotationIndexAndNameDataListener()).sheet() diff --git a/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataListener.java index 3108f97a..35829e0e 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataListener.java @@ -3,35 +3,40 @@ package com.alibaba.easyexcel.test.core.celldata; import java.util.ArrayList; import java.util.List; -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.fastjson.JSON; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author Jiaju Zhuang */ -public class CellDataDataListener extends AnalysisEventListener { +public class CellDataDataListener extends AnalysisEventListener { private static final Logger LOGGER = LoggerFactory.getLogger(CellDataDataListener.class); - List list = new ArrayList(); + List list = new ArrayList<>(); @Override - public void invoke(CellDataData data, AnalysisContext context) { + public void invoke(CellDataReadData data, AnalysisContext context) { list.add(data); } @Override public void doAfterAllAnalysed(AnalysisContext context) { Assert.assertEquals(list.size(), 1); - CellDataData cellDataData = list.get(0); + CellDataReadData cellDataData = list.get(0); - Assert.assertEquals(cellDataData.getDate().getStringValue(), "2020年01月01日"); + Assert.assertEquals("2020年01月01日", cellDataData.getDate().getData()); Assert.assertEquals((long)cellDataData.getInteger1().getData(), 2L); Assert.assertEquals((long)cellDataData.getInteger2(), 2L); - Assert.assertEquals(cellDataData.getFormulaValue().getFormulaValue(), "B2+C2"); + if (context.readWorkbookHolder().getExcelType() != ExcelTypeEnum.CSV) { + Assert.assertEquals(cellDataData.getFormulaValue().getFormulaData().getFormulaValue(), "B2+C2"); + } else { + Assert.assertNull(cellDataData.getFormulaValue().getData()); + } LOGGER.debug("First row:{}", JSON.toJSONString(list.get(0))); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataTest.java index 4615cdbc..0fd2f225 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataDataTest.java @@ -3,26 +3,21 @@ package com.alibaba.easyexcel.test.core.celldata; import java.io.File; import java.math.BigDecimal; import java.util.ArrayList; -import java.util.Date; import java.util.List; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; - -import com.alibaba.easyexcel.test.core.simple.SimpleData; -import com.alibaba.easyexcel.test.core.simple.SimpleDataListener; -import com.alibaba.easyexcel.test.core.simple.SimpleDataSheetNameListener; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.FormulaData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.DateUtils; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** - * * @author Jiaju Zhuang */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -30,11 +25,14 @@ public class CellDataDataTest { private static File file07; private static File file03; + private static File fileCsv; + @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("cellData07.xlsx"); file03 = TestFileUtil.createNewFile("cellData03.xls"); + fileCsv = TestFileUtil.createNewFile("cellDataCsv.csv"); } @Test @@ -47,23 +45,30 @@ public class CellDataDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() throws Exception { + readAndWrite(fileCsv); + } + + private void readAndWrite(File file) throws Exception { - EasyExcel.write(file, CellDataData.class).sheet().doWrite(data()); - EasyExcel.read(file, CellDataData.class, new CellDataDataListener()).sheet().doRead(); + EasyExcel.write(file, CellDataWriteData.class).sheet().doWrite(data()); + EasyExcel.read(file, CellDataReadData.class, new CellDataDataListener()).sheet().doRead(); } - private List data() throws Exception { - List list = new ArrayList(); - CellDataData cellDataData = new CellDataData(); - cellDataData.setDate(new CellData(DateUtils.parseDate("2020-01-01 01:01:01"))); - CellData integer1 = new CellData(); + private List data() throws Exception { + List list = new ArrayList<>(); + CellDataWriteData cellDataData = new CellDataWriteData(); + cellDataData.setDate(new WriteCellData<>(DateUtils.parseDate("2020-01-01 01:01:01"))); + WriteCellData integer1 = new WriteCellData<>(); integer1.setType(CellDataTypeEnum.NUMBER); integer1.setNumberValue(BigDecimal.valueOf(2L)); cellDataData.setInteger1(integer1); cellDataData.setInteger2(2); - CellData formulaValue = new CellData(); - formulaValue.setFormula(Boolean.TRUE); - formulaValue.setFormulaValue("B2+C2"); + WriteCellData formulaValue = new WriteCellData<>(); + FormulaData formulaData = new FormulaData(); + formulaValue.setFormulaData(formulaData); + formulaData.setFormulaValue("B2+C2"); cellDataData.setFormulaValue(formulaValue); list.add(cellDataData); return list; diff --git a/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataReadData.java b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataReadData.java new file mode 100644 index 00000000..b8322073 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataReadData.java @@ -0,0 +1,18 @@ +package com.alibaba.easyexcel.test.core.celldata; + +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.metadata.data.ReadCellData; + +import lombok.Data; + +/** + * @author Jiaju Zhuang + */ +@Data +public class CellDataReadData { + @DateTimeFormat("yyyy年MM月dd日") + private ReadCellData date; + private ReadCellData integer1; + private Integer integer2; + private ReadCellData formulaValue; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataData.java b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataWriteData.java similarity index 53% rename from src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataData.java rename to src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataWriteData.java index a4e624fb..69ed7bbf 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataData.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/celldata/CellDataWriteData.java @@ -2,9 +2,8 @@ package com.alibaba.easyexcel.test.core.celldata; import java.util.Date; -import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.format.DateTimeFormat; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.WriteCellData; import lombok.Data; @@ -12,10 +11,10 @@ import lombok.Data; * @author Jiaju Zhuang */ @Data -public class CellDataData { +public class CellDataWriteData { @DateTimeFormat("yyyy年MM月dd日") - private CellData date; - private CellData integer1; + private WriteCellData date; + private WriteCellData integer1; private Integer integer2; - private CellData formulaValue; + private WriteCellData formulaValue; } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityData.java b/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityData.java deleted file mode 100644 index 45b7f63a..00000000 --- a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityData.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.alibaba.easyexcel.test.core.compatibility; - -import com.alibaba.excel.annotation.ExcelProperty; -import com.alibaba.excel.metadata.BaseRowModel; - -import lombok.Data; - -/** - * @author Jiaju Zhuang - */ -@Data -public class CompatibilityData extends BaseRowModel { - @ExcelProperty("字符串标题0") - private String string0; - @ExcelProperty("字符串标题1") - private String string1; -} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataListener.java deleted file mode 100644 index 29774ba9..00000000 --- a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataListener.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.alibaba.easyexcel.test.core.compatibility; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.easyexcel.test.core.annotation.AnnotationDataListener; -import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.fastjson.JSON; - -/** - * @author Jiaju Zhuang - */ -public class CompatibilityDataListener extends AnalysisEventListener> { - private static final Logger LOGGER = LoggerFactory.getLogger(AnnotationDataListener.class); - List> list = new ArrayList>(); - - @Override - public void invoke(List data, AnalysisContext context) { - list.add(data); - } - - @Override - public void doAfterAllAnalysed(AnalysisContext context) { - Assert.assertEquals(list.size(), 10); - List data = list.get(0); - Assert.assertEquals(data.get(0), "字符串00"); - LOGGER.debug("First row:{}", JSON.toJSONString(list.get(0))); - } -} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataTest.java deleted file mode 100644 index 258f055c..00000000 --- a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataTest.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.alibaba.easyexcel.test.core.compatibility; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.poi.ss.usermodel.IndexedColors; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.ExcelReader; -import com.alibaba.excel.ExcelWriter; -import com.alibaba.excel.metadata.Font; -import com.alibaba.excel.metadata.Sheet; -import com.alibaba.excel.metadata.Table; -import com.alibaba.excel.metadata.TableStyle; -import com.alibaba.excel.parameter.AnalysisParam; -import com.alibaba.excel.parameter.GenerateParam; - -/** - * - * @author Jiaju Zhuang - */ -public class CompatibilityDataTest { - - private static File file07; - private static File file03; - - @BeforeClass - public static void init() { - file07 = TestFileUtil.createNewFile("compatibility07.xlsx"); - file03 = TestFileUtil.createNewFile("compatibility03.xls"); - } - - @Test - public void t01ReadAndWrite07() throws Exception { - readAndWrite(file07); - } - - @Test - public void t02ReadAndWrite03() throws Exception { - readAndWrite(file03); - } - - private void readAndWrite(File file) throws Exception { - OutputStream out = new FileOutputStream(file); - GenerateParam generateParam = new GenerateParam("", null, out); - generateParam.setSheetName(""); - generateParam.setOutputStream(out); - generateParam.setClazz(null); - ExcelWriter writer = new ExcelWriter(generateParam); - // sheet1 width,string head,string data - Sheet sheet1 = new Sheet(1, 3); - sheet1.setSheetName("第一个sheet"); - Map columnWidth = new HashMap(); - columnWidth.put(0, 10000); - columnWidth.put(1, 50000); - sheet1.setColumnWidthMap(columnWidth); - sheet1.setHead(head()); - writer.write1(listData(), sheet1); - - // sheet2 style,class head - Sheet sheet2 = new Sheet(2, 3, CompatibilityData.class, "第二个sheet", null); - sheet2.setStartRow(5); - sheet2.setTableStyle(style()); - writer.write(data(), sheet2); - writer.merge(8, 8, 0, 1); - - // sheet3 table - Sheet sheet3 = new Sheet(3, 0); - sheet3.setSheetName("第三个sheet"); - - Table table1 = new Table(1); - table1.setHead(head()); - writer.write1(listData(), sheet3, table1); - - Table table2 = new Table(2); - table2.setClazz(CompatibilityData.class); - writer.write(data(), sheet3, table2); - - writer.finish(); - out.close(); - - InputStream inputStream = new FileInputStream(file); - List data = EasyExcel.read(inputStream, new Sheet(1, 1)); - Assert.assertEquals(data.size(), 1); - List dataList = (List)data.get(0); - Assert.assertEquals(dataList.get(0), "字符串00"); - inputStream.close(); - - inputStream = new FileInputStream(file); - AnalysisParam param = new AnalysisParam(inputStream, null, new Object()); - param.setIn(inputStream); - param.setExcelTypeEnum(null); - param.setCustomContent(null); - ExcelReader excelReader = new ExcelReader(param, new CompatibilityDataListener()); - excelReader.read(new Sheet(2, 6)); - Assert.assertEquals(excelReader.getSheets().size(), 3); - Assert.assertTrue(excelReader.getAnalysisContext() != null); - inputStream.close(); - } - - private List> head() { - List> list = new ArrayList>(); - List head0 = new ArrayList(); - head0.add("字符串标题0"); - List head1 = new ArrayList(); - head1.add("字符串标题1"); - list.add(head0); - list.add(head1); - return list; - } - - private List> listData() { - List> list = new ArrayList>(); - List data0 = new ArrayList(); - data0.add("字符串00"); - data0.add(11); - list.add(data0); - return list; - } - - private List data() { - List list = new ArrayList(); - for (int i = 0; i < 10; i++) { - CompatibilityData data = new CompatibilityData(); - data.setString0("字符串0" + i); - data.setString1("字符串1" + i); - list.add(data); - } - return list; - } - - public TableStyle style() { - TableStyle tableStyle = new TableStyle(); - Font headFont = new Font(); - headFont.setBold(true); - headFont.setFontHeightInPoints((short)22); - headFont.setFontName("楷体"); - tableStyle.setTableHeadFont(headFont); - tableStyle.setTableHeadBackGroundColor(IndexedColors.BLUE); - - Font contentFont = new Font(); - contentFont.setBold(true); - contentFont.setFontHeightInPoints((short)22); - contentFont.setFontName("黑体"); - tableStyle.setTableContentFont(contentFont); - tableStyle.setTableContentBackGroundColor(IndexedColors.GREEN); - return tableStyle; - } -} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityParameterDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityParameterDataTest.java deleted file mode 100644 index 2e3b7355..00000000 --- a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityParameterDataTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.alibaba.easyexcel.test.core.compatibility; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import org.junit.BeforeClass; -import org.junit.Test; - -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.ExcelReader; -import com.alibaba.excel.ExcelWriter; -import com.alibaba.excel.metadata.Sheet; - -/** - * - * @author Jiaju Zhuang - */ -public class CompatibilityParameterDataTest { - - private static File file; - - @BeforeClass - public static void init() { - file = TestFileUtil.createNewFile("compatibilityParameter.xlsx"); - } - - @Test - public void t01ReadAndWrite() throws Exception { - readAndWrite1(file); - readAndWrite2(file); - readAndWrite3(file); - readAndWrite4(file); - readAndWrite5(file); - readAndWrite6(file); - } - - private void readAndWrite1(File file) throws Exception { - OutputStream out = new FileOutputStream(file); - ExcelWriter writer = EasyExcel.getWriter(out); - Sheet sheet1 = new Sheet(1, 0); - sheet1.setSheetName("第一个sheet"); - writer.write0(data(), sheet1); - writer.finish(); - out.close(); - - InputStream inputStream = new FileInputStream(file); - EasyExcel.readBySax(inputStream, new Sheet(1, 0), new CompatibilityDataListener()); - inputStream.close(); - } - - private void readAndWrite2(File file) throws Exception { - OutputStream out = new FileOutputStream(file); - ExcelWriter writer = EasyExcel.getWriter(out, null, false); - Sheet sheet1 = new Sheet(1, 0); - sheet1.setSheetName("第一个sheet"); - writer.write0(data(), sheet1); - writer.finish(); - out.close(); - - InputStream inputStream = new FileInputStream(file); - EasyExcel.readBySax(inputStream, new Sheet(1, 0), new CompatibilityDataListener()); - inputStream.close(); - } - - private void readAndWrite3(File file) throws Exception { - OutputStream out = new FileOutputStream(file); - ExcelWriter writer = new ExcelWriter(out, null); - Sheet sheet1 = new Sheet(1, 0); - sheet1.setSheetName("第一个sheet"); - writer.write0(data(), sheet1); - writer.finish(); - out.close(); - - InputStream inputStream = new FileInputStream(file); - ExcelReader excelReader = new ExcelReader(inputStream, null, null, new CompatibilityDataListener()); - excelReader.read(new Sheet(1, 0)); - inputStream.close(); - - } - - private void readAndWrite4(File file) throws Exception { - OutputStream out = new FileOutputStream(file); - ExcelWriter writer = new ExcelWriter(null, out, null, null); - Sheet sheet1 = new Sheet(1, 0); - sheet1.setSheetName("第一个sheet"); - writer.write0(data(), sheet1, null); - writer.finish(); - out.close(); - - InputStream inputStream = new FileInputStream(file); - ExcelReader excelReader = new ExcelReader(inputStream, null, new CompatibilityDataListener()); - excelReader.read(new Sheet(1, 0)); - inputStream.close(); - } - - private void readAndWrite5(File file) throws Exception { - OutputStream out = new FileOutputStream(file); - ExcelWriter writer = EasyExcel.getWriterWithTemp(null, out, null, false); - Sheet sheet1 = new Sheet(1, 0); - sheet1.setSheetName("第一个sheet"); - writer.write0(data(), sheet1, null); - writer.finish(); - out.close(); - - InputStream inputStream = new FileInputStream(file); - ExcelReader excelReader = EasyExcel.getReader(inputStream, new CompatibilityDataListener()); - excelReader.read(new Sheet(1, 0)); - inputStream.close(); - } - - private void readAndWrite6(File file) throws Exception { - OutputStream out = new FileOutputStream(file); - ExcelWriter writer = EasyExcel.getWriterWithTempAndHandler(null, out, null, false, null); - Sheet sheet1 = new Sheet(1, 0); - sheet1.setSheetName("第一个sheet"); - writer.write0(data(), sheet1, null); - writer.finish(); - out.close(); - - InputStream inputStream = new FileInputStream(file); - ExcelReader excelReader = EasyExcel.getReader(inputStream, new CompatibilityDataListener()); - excelReader.read(new Sheet(1, 0)); - inputStream.close(); - } - - private List data() { - List list = new ArrayList(); - for (int i = 0; i < 10; i++) { - CompatibilityData data = new CompatibilityData(); - data.setString0("字符串0" + i); - data.setString1("字符串1" + i); - list.add(data); - } - return list; - } - -} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityReadData.java b/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityReadData.java deleted file mode 100644 index ba062a5f..00000000 --- a/src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityReadData.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.alibaba.easyexcel.test.core.compatibility; - -import com.alibaba.excel.metadata.BaseRowModel; - -import lombok.Data; - -/** - * @author Jiaju Zhuang - */ -@Data -public class CompatibilityReadData extends BaseRowModel { - private String string0; - private String string1; -} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java index 210ca142..0a71d25a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataListener.java @@ -1,43 +1,46 @@ package com.alibaba.easyexcel.test.core.converter; import java.math.BigDecimal; +import java.math.BigInteger; import java.text.ParseException; import java.util.ArrayList; import java.util.List; -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelCommonException; import com.alibaba.excel.util.DateUtils; import com.alibaba.fastjson.JSON; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author Jiaju Zhuang */ -public class ConverterDataListener extends AnalysisEventListener { +public class ConverterDataListener extends AnalysisEventListener { private static final Logger LOGGER = LoggerFactory.getLogger(ConverterDataListener.class); - List list = new ArrayList(); + private List list = new ArrayList<>(); @Override - public void invoke(ConverterData data, AnalysisContext context) { + public void invoke(ConverterReadData data, AnalysisContext context) { list.add(data); } @Override public void doAfterAllAnalysed(AnalysisContext context) { Assert.assertEquals(list.size(), 1); - ConverterData data = list.get(0); + ConverterReadData data = list.get(0); try { Assert.assertEquals(DateUtils.parseDate("2020-01-01 01:01:01"), data.getDate()); } catch (ParseException e) { throw new ExcelCommonException("Test Exception", e); } + Assert.assertEquals(DateUtils.parseLocalDateTime("2020-01-01 01:01:01", null, null), data.getLocalDateTime()); Assert.assertEquals(data.getBooleanData(), Boolean.TRUE); Assert.assertEquals(data.getBigDecimal().doubleValue(), BigDecimal.ONE.doubleValue(), 0.0); + Assert.assertEquals(data.getBigInteger().intValue(), BigInteger.ONE.intValue(), 0.0); Assert.assertEquals((long)data.getLongData(), 1L); Assert.assertEquals((long)data.getIntegerData(), 1L); Assert.assertEquals((long)data.getShortData(), 1L); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataTest.java index a339e9ef..b2943522 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataTest.java @@ -3,22 +3,22 @@ package com.alibaba.easyexcel.test.core.converter; import java.io.File; import java.io.InputStream; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.FileUtils; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** - * * @author Jiaju Zhuang */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -26,6 +26,7 @@ public class ConverterDataTest { private static File file07; private static File file03; + private static File fileCsv; private static File fileImage07; private static File fileImage03; @@ -33,6 +34,7 @@ public class ConverterDataTest { public static void init() { file07 = TestFileUtil.createNewFile("converter07.xlsx"); file03 = TestFileUtil.createNewFile("converter03.xls"); + fileCsv = TestFileUtil.createNewFile("converterCsv.csv"); fileImage07 = TestFileUtil.createNewFile("converterImage07.xlsx"); fileImage03 = TestFileUtil.createNewFile("converterImage03.xls"); } @@ -47,35 +49,45 @@ public class ConverterDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() throws Exception { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) throws Exception { - EasyExcel.write(file, ConverterData.class).sheet().doWrite(data()); - EasyExcel.read(file, ConverterData.class, new ConverterDataListener()).sheet().doRead(); + EasyExcel.write(file, ConverterWriteData.class).sheet().doWrite(data()); + EasyExcel.read(file, ConverterReadData.class, new ConverterDataListener()).sheet().doRead(); } @Test - public void t03ReadAllConverter07() { + public void t11ReadAllConverter07() { readAllConverter("converter" + File.separator + "converter07.xlsx"); } @Test - public void t04ReadAllConverter03() { + public void t12ReadAllConverter03() { readAllConverter("converter" + File.separator + "converter03.xls"); } @Test - public void t05WriteImage07() throws Exception { + public void t13ReadAllConverterCsv() { + readAllConverter("converter" + File.separator + "converterCsv.csv"); + } + + @Test + public void t21WriteImage07() throws Exception { writeImage(fileImage07); } @Test - public void t06WriteImage03() throws Exception { + public void t22WriteImage03() throws Exception { writeImage(fileImage03); } private void writeImage(File file) throws Exception { InputStream inputStream = null; try { - List list = new ArrayList(); + List list = new ArrayList<>(); ImageData imageData = new ImageData(); list.add(imageData); String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg"; @@ -97,21 +109,23 @@ public class ConverterDataTest { .sheet().doRead(); } - private List data() throws Exception { - List list = new ArrayList(); - ConverterData converterData = new ConverterData(); - converterData.setDate(DateUtils.parseDate("2020-01-01 01:01:01")); - converterData.setBooleanData(Boolean.TRUE); - converterData.setBigDecimal(BigDecimal.ONE); - converterData.setLongData(1L); - converterData.setIntegerData(1); - converterData.setShortData((short)1); - converterData.setByteData((byte)1); - converterData.setDoubleData(1.0); - converterData.setFloatData((float)1.0); - converterData.setString("测试"); - converterData.setCellData(new CellData("自定义")); - list.add(converterData); + private List data() throws Exception { + List list = new ArrayList(); + ConverterWriteData converterWriteData = new ConverterWriteData(); + converterWriteData.setDate(DateUtils.parseDate("2020-01-01 01:01:01")); + converterWriteData.setLocalDateTime(DateUtils.parseLocalDateTime("2020-01-01 01:01:01", null, null)); + converterWriteData.setBooleanData(Boolean.TRUE); + converterWriteData.setBigDecimal(BigDecimal.ONE); + converterWriteData.setBigInteger(BigInteger.ONE); + converterWriteData.setLongData(1L); + converterWriteData.setIntegerData(1); + converterWriteData.setShortData((short)1); + converterWriteData.setByteData((byte)1); + converterWriteData.setDoubleData(1.0); + converterWriteData.setFloatData((float)1.0); + converterWriteData.setString("测试"); + converterWriteData.setCellData(new WriteCellData<>("自定义")); + list.add(converterWriteData); return list; } } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterData.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterReadData.java similarity index 72% rename from src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterData.java rename to src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterReadData.java index 88469470..8fa78f7e 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterData.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterReadData.java @@ -1,10 +1,12 @@ package com.alibaba.easyexcel.test.core.converter; import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDateTime; import java.util.Date; import com.alibaba.excel.annotation.ExcelProperty; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; import lombok.Data; @@ -12,13 +14,17 @@ import lombok.Data; * @author Jiaju Zhuang */ @Data -public class ConverterData { +public class ConverterReadData { @ExcelProperty("日期") private Date date; + @ExcelProperty("本地日期") + private LocalDateTime localDateTime; @ExcelProperty("布尔") private Boolean booleanData; @ExcelProperty("大数") private BigDecimal bigDecimal; + @ExcelProperty("大整数") + private BigInteger bigInteger; @ExcelProperty("长整型") private long longData; @ExcelProperty("整型") @@ -34,5 +40,5 @@ public class ConverterData { @ExcelProperty("字符串") private String string; @ExcelProperty("自定义") - private CellData cellData; + private ReadCellData cellData; } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterWriteData.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterWriteData.java new file mode 100644 index 00000000..68c34423 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterWriteData.java @@ -0,0 +1,44 @@ +package com.alibaba.easyexcel.test.core.converter; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDateTime; +import java.util.Date; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.metadata.data.WriteCellData; + +import lombok.Data; + +/** + * @author Jiaju Zhuang + */ +@Data +public class ConverterWriteData { + @ExcelProperty("日期") + private Date date; + @ExcelProperty("本地日期") + private LocalDateTime localDateTime; + @ExcelProperty("布尔") + private Boolean booleanData; + @ExcelProperty("大数") + private BigDecimal bigDecimal; + @ExcelProperty("大整数") + private BigInteger bigInteger; + @ExcelProperty("长整型") + private long longData; + @ExcelProperty("整型") + private Integer integerData; + @ExcelProperty("短整型") + private Short shortData; + @ExcelProperty("字节型") + private Byte byteData; + @ExcelProperty("双精度浮点型") + private double doubleData; + @ExcelProperty("浮点型") + private Float floatData; + @ExcelProperty("字符串") + private String string; + @ExcelProperty("自定义") + private WriteCellData cellData; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java index 4f758a02..cccee710 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java @@ -1,6 +1,8 @@ package com.alibaba.easyexcel.test.core.converter; import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDateTime; import java.util.Date; import lombok.Data; @@ -13,6 +15,9 @@ public class ReadAllConverterData { private BigDecimal bigDecimalBoolean; private BigDecimal bigDecimalNumber; private BigDecimal bigDecimalString; + private BigInteger bigIntegerBoolean; + private BigInteger bigIntegerNumber; + private BigInteger bigIntegerString; private Boolean booleanBoolean; private Boolean booleanNumber; private Boolean booleanString; @@ -21,6 +26,8 @@ public class ReadAllConverterData { private Byte byteString; private Date dateNumber; private Date dateString; + private LocalDateTime localDateTimeNumber; + private LocalDateTime localDateTimeString; private Double doubleBoolean; private Double doubleNumber; private Double doubleString; diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java index d5da81ad..8516cd5b 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java @@ -1,20 +1,22 @@ package com.alibaba.easyexcel.test.core.converter; import java.math.BigDecimal; +import java.math.BigInteger; import java.text.ParseException; import java.util.ArrayList; import java.util.List; -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelCommonException; +import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.DateUtils; import com.alibaba.fastjson.JSON; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author Jiaju Zhuang */ @@ -34,6 +36,9 @@ public class ReadAllConverterDataListener extends AnalysisEventListener excludeColumnIndexes = new HashSet(); @@ -147,7 +171,6 @@ public class ExcludeOrIncludeDataTest { Assert.assertEquals("column3", record.get(1)); } - private List data() { List list = new ArrayList(); ExcludeOrIncludeData excludeOrIncludeData = new ExcludeOrIncludeData(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandler.java b/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandler.java index c762db79..a6f07014 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandler.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandler.java @@ -2,12 +2,8 @@ package com.alibaba.easyexcel.test.core.handler; import java.util.List; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.junit.Assert; - -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.handler.RowWriteHandler; import com.alibaba.excel.write.handler.SheetWriteHandler; @@ -16,9 +12,11 @@ import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.junit.Assert; + /** - * - * * @author JiaJu Zhuang **/ public class WriteHandler implements WorkbookWriteHandler, SheetWriteHandler, RowWriteHandler, CellWriteHandler { @@ -36,7 +34,6 @@ public class WriteHandler implements WorkbookWriteHandler, SheetWriteHandler, Ro private long afterWorkbookCreate = 0L; private long afterWorkbookDispose = 0L; - @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { @@ -80,7 +77,7 @@ public class WriteHandler implements WorkbookWriteHandler, SheetWriteHandler, Ro @Override public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + WriteCellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { Assert.assertEquals(1L, beforeCellCreate); Assert.assertEquals(1L, afterCellCreate); Assert.assertEquals(0L, afterCellDataConverted); @@ -98,7 +95,7 @@ public class WriteHandler implements WorkbookWriteHandler, SheetWriteHandler, Ro @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { if (isHead) { Assert.assertEquals(1L, beforeCellCreate); Assert.assertEquals(1L, afterCellCreate); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandlerTest.java b/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandlerTest.java index a96d133e..a3354f35 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandlerTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/handler/WriteHandlerTest.java @@ -1,22 +1,17 @@ package com.alibaba.easyexcel.test.core.handler; import java.io.File; -import java.text.ParseException; import java.util.ArrayList; import java.util.List; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -import com.alibaba.easyexcel.test.core.head.ListHeadDataListener; -import com.alibaba.easyexcel.test.core.simple.SimpleData; -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.util.DateUtils; -import com.alibaba.excel.write.handler.WorkbookWriteHandler; - /** * * @author Jiaju Zhuang @@ -26,11 +21,14 @@ public class WriteHandlerTest { private static File file07; private static File file03; + private static File fileCsv; + @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("writeHandler07.xlsx"); file03 = TestFileUtil.createNewFile("writeHandler03.xls"); + fileCsv = TestFileUtil.createNewFile("writeHandlerCsv.csv"); } @Test @@ -44,27 +42,42 @@ public class WriteHandlerTest { } @Test - public void t03SheetWrite07() throws Exception { + public void t03WorkbookWriteCsv() throws Exception { + workbookWrite(fileCsv); + } + + + @Test + public void t11SheetWrite07() throws Exception { sheetWrite(file07); } @Test - public void t04SheetWrite03() throws Exception { + public void t12SheetWrite03() throws Exception { sheetWrite(file03); } @Test - public void t05TableWrite07() throws Exception { - workbookWrite(file07); + public void t13SheetWriteCsv() throws Exception { + sheetWrite(fileCsv); + } + + @Test + public void t21TableWrite07() throws Exception { tableWrite(file07); } @Test - public void t06TableWrite03() throws Exception { + public void t22TableWrite03() throws Exception { tableWrite(file03); } + @Test + public void t23TableWriteCsv() throws Exception { + tableWrite(fileCsv); + } + private void workbookWrite(File file) { WriteHandler writeHandler = new WriteHandler(); EasyExcel.write(file).head(WriteHandlerData.class).registerWriteHandler(writeHandler).sheet().doWrite(data()); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/head/ComplexHeadDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/head/ComplexHeadDataTest.java index 25f7fed5..07340c3b 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/head/ComplexHeadDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/head/ComplexHeadDataTest.java @@ -4,29 +4,35 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.Test; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** - * * @author Jiaju Zhuang */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ComplexHeadDataTest { private static File file07; private static File file03; + private static File fileCsv; private static File file07AutomaticMergeHead; private static File file03AutomaticMergeHead; + private static File fileCsvAutomaticMergeHead; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("complexHead07.xlsx"); file03 = TestFileUtil.createNewFile("complexHead03.xls"); + fileCsv = TestFileUtil.createNewFile("complexHeadCsv.csv"); file07AutomaticMergeHead = TestFileUtil.createNewFile("complexHeadAutomaticMergeHead07.xlsx"); file03AutomaticMergeHead = TestFileUtil.createNewFile("complexHeadAutomaticMergeHead03.xls"); + fileCsvAutomaticMergeHead = TestFileUtil.createNewFile("complexHeadAutomaticMergeHeadCsv.csv"); } @Test @@ -39,6 +45,11 @@ public class ComplexHeadDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) { EasyExcel.write(file, ComplexHeadData.class).sheet().doWrite(data()); EasyExcel.read(file, ComplexHeadData.class, new ComplexDataListener()) @@ -46,16 +57,21 @@ public class ComplexHeadDataTest { } @Test - public void t03ReadAndWriteAutomaticMergeHead07() { - readAndWriteAutomaticMergeHead07(file07AutomaticMergeHead); + public void t11ReadAndWriteAutomaticMergeHead07() { + readAndWriteAutomaticMergeHead(file07AutomaticMergeHead); + } + + @Test + public void t12ReadAndWriteAutomaticMergeHead03() { + readAndWriteAutomaticMergeHead(file03AutomaticMergeHead); } @Test - public void t04ReadAndWriteAutomaticMergeHead0703() { - readAndWriteAutomaticMergeHead07(file03AutomaticMergeHead); + public void t13ReadAndWriteAutomaticMergeHeadCsv() { + readAndWriteAutomaticMergeHead(fileCsvAutomaticMergeHead); } - private void readAndWriteAutomaticMergeHead07(File file) { + private void readAndWriteAutomaticMergeHead(File file) { EasyExcel.write(file, ComplexHeadData.class).automaticMergeHead(Boolean.FALSE).sheet().doWrite(data()); EasyExcel.read(file, ComplexHeadData.class, new ComplexDataListener()).sheet().doRead(); } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataTest.java index 6e63a0b3..073c0e9c 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataTest.java @@ -5,26 +5,32 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.Test; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.util.DateUtils; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** * * @author Jiaju Zhuang */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ListHeadDataTest { private static File file07; private static File file03; + private static File fileCsv; + @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("listHead07.xlsx"); file03 = TestFileUtil.createNewFile("listHead03.xls"); + fileCsv = TestFileUtil.createNewFile("listHeadCsv.csv"); } @Test @@ -37,6 +43,11 @@ public class ListHeadDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() throws Exception { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) throws Exception { EasyExcel.write(file).head(head()).sheet().doWrite(data()); EasyExcel.read(file).registerReadListener(new ListHeadDataListener()).sheet().doRead(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/head/NoHeadDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/head/NoHeadDataTest.java index a62adbb8..b08e4630 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/head/NoHeadDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/head/NoHeadDataTest.java @@ -4,25 +4,29 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.Test; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** - * * @author Jiaju Zhuang */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class NoHeadDataTest { private static File file07; private static File file03; + private static File fileCsv; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("noHead07.xlsx"); file03 = TestFileUtil.createNewFile("noHead03.xls"); + fileCsv = TestFileUtil.createNewFile("noHeadCsv.csv"); } @Test @@ -35,6 +39,11 @@ public class NoHeadDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) { EasyExcel.write(file, NoHeadData.class).needHead(Boolean.FALSE).sheet().doWrite(data()); EasyExcel.read(file, NoHeadData.class, new NoHeadDataListener()).headRowNumber(0).sheet().doRead(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataListener.java index 23a8843c..dafe25fa 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataListener.java @@ -1,13 +1,14 @@ package com.alibaba.easyexcel.test.core.large; -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.fastjson.JSON; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author Jiaju Zhuang */ @@ -22,13 +23,17 @@ public class LargeDataListener extends AnalysisEventListener { } count++; if (count % 100000 == 0) { - LOGGER.info("Already read:{}", count); + LOGGER.info("Already read:{},{}", count, JSON.toJSONString(data)); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { LOGGER.info("Large row count:{}", count); - Assert.assertEquals(count, 464509); + if (context.readWorkbookHolder().getExcelType() != ExcelTypeEnum.CSV) { + Assert.assertEquals(count, 464509); + } else { + Assert.assertEquals(count, 499999); + } } } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java index fa32433a..957894e2 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/large/LargeDataTest.java @@ -4,31 +4,34 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.easyexcel.test.demo.write.DemoData; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** - * * @author Jiaju Zhuang */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class LargeDataTest { private static final Logger LOGGER = LoggerFactory.getLogger(LargeDataTest.class); private static File fileFill07; private static File template07; + private static File fileCsv; private int i = 0; @BeforeClass public static void init() { fileFill07 = TestFileUtil.createNewFile("largefill07.xlsx"); template07 = TestFileUtil.readFile("large" + File.separator + "fill.xlsx"); + fileCsv = TestFileUtil.createNewFile("largefileCsv.csv"); } @Test @@ -50,8 +53,27 @@ public class LargeDataTest { excelWriter.finish(); } + @Test + public void t03ReadAndWriteCsv() { + // write + long start = System.currentTimeMillis(); + ExcelWriter excelWriter = EasyExcel.write(fileCsv).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + for (int j = 0; j < 100; j++) { + excelWriter.write(data(), writeSheet); + LOGGER.info("{} write success.", j); + } + excelWriter.finish(); + LOGGER.info("CSV large data total time spent:{}", System.currentTimeMillis() - start); + + // read + start = System.currentTimeMillis(); + EasyExcel.read(fileCsv, LargeData.class, new LargeDataListener()).sheet().doRead(); + LOGGER.info("CSV large data total time spent:{}", System.currentTimeMillis() - start); + } + private List data() { - List list = new ArrayList(); + List list = new ArrayList<>(); int size = i + 5000; for (; i < size; i++) { LargeData largeData = new LargeData(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java index 44e2f55b..c69e3ae4 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/multiplesheets/MultipleSheetsDataTest.java @@ -3,17 +3,17 @@ package com.alibaba.easyexcel.test.core.multiplesheets; import java.io.File; import java.util.List; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelReader; +import com.alibaba.excel.read.metadata.ReadSheet; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.ExcelReader; -import com.alibaba.excel.read.metadata.ReadSheet; - /** * * @author Jiaju Zhuang @@ -57,7 +57,7 @@ public class MultipleSheetsDataTest { int count = 1; for (ReadSheet readSheet : sheets) { excelReader.read(readSheet); - Assert.assertEquals((long)multipleSheetsListener.getList().size(), (long)count); + Assert.assertEquals(multipleSheetsListener.getList().size(), count); count++; } excelReader.finish(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/nomodel/NoModelDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/nomodel/NoModelDataTest.java new file mode 100644 index 00000000..262ae35d --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/nomodel/NoModelDataTest.java @@ -0,0 +1,86 @@ +package com.alibaba.easyexcel.test.core.nomodel; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.util.DateUtils; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * @author Jiaju Zhuang + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class NoModelDataTest { + + private static File file07; + private static File file03; + private static File fileCsv; + private static File fileRepeat07; + private static File fileRepeat03; + private static File fileRepeatCsv; + + + @BeforeClass + public static void init() { + file07 = TestFileUtil.createNewFile("noModel07.xlsx"); + file03 = TestFileUtil.createNewFile("noModel03.xls"); + fileCsv = TestFileUtil.createNewFile("noModelCsv.csv"); + fileRepeat07 = TestFileUtil.createNewFile("noModelRepeat07.xlsx"); + fileRepeat03 = TestFileUtil.createNewFile("noModelRepeat03.xls"); + fileRepeatCsv = TestFileUtil.createNewFile("noModelRepeatCsv.csv"); + } + + @Test + public void t01ReadAndWrite07() throws Exception { + readAndWrite(file07, fileRepeat07); + } + + @Test + public void t02ReadAndWrite03() throws Exception { + readAndWrite(file03, fileRepeat03); + } + + @Test + public void t03ReadAndWriteCsv() throws Exception { + readAndWrite(fileCsv, fileRepeatCsv); + } + + private void readAndWrite(File file, File fileRepeat) throws Exception { + EasyExcel.write(file).sheet().doWrite(data()); + List> result = EasyExcel.read(file).headRowNumber(0).sheet().doReadSync(); + Assert.assertEquals(10, result.size()); + Map data10 = result.get(9); + Assert.assertEquals("string19", data10.get(0)); + Assert.assertEquals("109", data10.get(1)); + Assert.assertEquals("2020-01-01 01:01:01", data10.get(2)); + + EasyExcel.write(fileRepeat).sheet().doWrite(result); + result = EasyExcel.read(fileRepeat).headRowNumber(0).sheet().doReadSync(); + Assert.assertEquals(10, result.size()); + data10 = result.get(9); + Assert.assertEquals("string19", data10.get(0)); + Assert.assertEquals("109", data10.get(1)); + Assert.assertEquals("2020-01-01 01:01:01", data10.get(2)); + } + + private List> data() throws Exception { + List> list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + List data = new ArrayList<>(); + data.add("string1" + i); + data.add(100 + i); + data.add(DateUtils.parseDate("2020-01-01 01:01:01")); + list.add(data); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelData.java b/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelData.java new file mode 100644 index 00000000..dd010fc7 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelData.java @@ -0,0 +1,16 @@ +package com.alibaba.easyexcel.test.core.noncamel; + +import lombok.Data; + +/** + * @author Jiaju Zhuang + */ +@Data +public class UnCamelData { + private String string1; + private String String2; + private String sTring3; + private String STring4; + private String STRING5; + private String STRing6; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelDataListener.java new file mode 100644 index 00000000..2f36d665 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelDataListener.java @@ -0,0 +1,49 @@ +package com.alibaba.easyexcel.test.core.noncamel; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.fastjson.JSON; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; + +/** + * @author Jiaju Zhuang + */ +@Slf4j +public class UnCamelDataListener extends AnalysisEventListener { + List list = new ArrayList<>(); + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + log.debug("Head is:{}", JSON.toJSONString(headMap)); + Assert.assertEquals(headMap.get(0), "string1"); + Assert.assertEquals(headMap.get(1), "String2"); + Assert.assertEquals(headMap.get(2), "sTring3"); + Assert.assertEquals(headMap.get(3), "STring4"); + Assert.assertEquals(headMap.get(4), "STRING5"); + Assert.assertEquals(headMap.get(5), "STRing6"); + } + + @Override + public void invoke(UnCamelData data, AnalysisContext context) { + list.add(data); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + Assert.assertEquals(list.size(), 10); + UnCamelData unCamelData = list.get(0); + Assert.assertEquals(unCamelData.getString1(), "string1"); + Assert.assertEquals(unCamelData.getString2(), "string2"); + Assert.assertEquals(unCamelData.getSTring3(), "string3"); + Assert.assertEquals(unCamelData.getSTring4(), "string4"); + Assert.assertEquals(unCamelData.getSTRING5(), "string5"); + Assert.assertEquals(unCamelData.getSTRing6(), "string6"); + log.debug("First row:{}", JSON.toJSONString(list.get(0))); + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelDataTest.java new file mode 100644 index 00000000..e8696c5a --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/noncamel/UnCamelDataTest.java @@ -0,0 +1,67 @@ +package com.alibaba.easyexcel.test.core.noncamel; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * @author Jiaju Zhuang + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class UnCamelDataTest { + + private static File file07; + private static File file03; + private static File fileCsv; + + + @BeforeClass + public static void init() { + file07 = TestFileUtil.createNewFile("unCame07.xlsx"); + file03 = TestFileUtil.createNewFile("unCame03.xls"); + fileCsv = TestFileUtil.createNewFile("unCameCsv.csv"); + } + + @Test + public void t01ReadAndWrite07() { + readAndWrite(file07); + } + + @Test + public void t02ReadAndWrite03() { + readAndWrite(file03); + } + + @Test + public void t03ReadAndWriteCsv() { + readAndWrite(fileCsv); + } + + private void readAndWrite(File file) { + EasyExcel.write(file, UnCamelData.class).sheet().doWrite(data()); + EasyExcel.read(file, UnCamelData.class, new UnCamelDataListener()).sheet().doRead(); + } + + private List data() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + UnCamelData unCamelData = new UnCamelData(); + unCamelData.setString1("string1"); + unCamelData.setString2("string2"); + unCamelData.setSTring3("string3"); + unCamelData.setSTring4("string4"); + unCamelData.setSTRING5("string5"); + unCamelData.setSTRing6("string6"); + list.add(unCamelData); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/parameter/ParameterDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/parameter/ParameterDataTest.java index c7c305de..4e0f2a09 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/parameter/ParameterDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/parameter/ParameterDataTest.java @@ -5,11 +5,6 @@ import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelReader; @@ -17,59 +12,79 @@ import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.cache.MapCache; import com.alibaba.excel.converters.string.StringStringConverter; import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** - * * @author Jiaju Zhuang */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ParameterDataTest { - private static File file; + private static File file07; + private static File fileCsv; @BeforeClass public static void init() { - file = TestFileUtil.createNewFile("parameter07.xlsx"); + file07 = TestFileUtil.createNewFile("parameter07.xlsx"); + fileCsv = TestFileUtil.createNewFile("parameterCsv.csv"); } @Test public void t01ReadAndWrite() throws Exception { - readAndWrite1(); - readAndWrite2(); - readAndWrite3(); - readAndWrite4(); - readAndWrite5(); - readAndWrite6(); - readAndWrite7(); + readAndWrite1(file07, ExcelTypeEnum.XLSX); + readAndWrite2(file07, ExcelTypeEnum.XLSX); + readAndWrite3(file07, ExcelTypeEnum.XLSX); + readAndWrite4(file07, ExcelTypeEnum.XLSX); + readAndWrite5(file07, ExcelTypeEnum.XLSX); + readAndWrite6(file07, ExcelTypeEnum.XLSX); + readAndWrite7(file07, ExcelTypeEnum.XLSX); } - private void readAndWrite1() { + @Test + public void t02ReadAndWrite() throws Exception { + readAndWrite1(fileCsv, ExcelTypeEnum.CSV); + readAndWrite2(fileCsv, ExcelTypeEnum.CSV); + readAndWrite3(fileCsv, ExcelTypeEnum.CSV); + readAndWrite4(fileCsv, ExcelTypeEnum.CSV); + readAndWrite5(fileCsv, ExcelTypeEnum.CSV); + readAndWrite6(fileCsv, ExcelTypeEnum.CSV); + readAndWrite7(fileCsv, ExcelTypeEnum.CSV); + } + + private void readAndWrite1(File file, ExcelTypeEnum type) { EasyExcel.write(file.getPath()).head(ParameterData.class).sheet().doWrite(data()); EasyExcel.read(file.getPath()).head(ParameterData.class).registerReadListener(new ParameterDataListener()) .sheet().doRead(); } - private void readAndWrite2() { + private void readAndWrite2(File file, ExcelTypeEnum type) { EasyExcel.write(file.getPath(), ParameterData.class).sheet().doWrite(data()); EasyExcel.read(file.getPath(), ParameterData.class, new ParameterDataListener()).sheet().doRead(); } - private void readAndWrite3() throws Exception { - EasyExcel.write(new FileOutputStream(file)).head(ParameterData.class).sheet().doWrite(data()); + private void readAndWrite3(File file, ExcelTypeEnum type) throws Exception { + EasyExcel.write(new FileOutputStream(file)).excelType(type).head(ParameterData.class).sheet() + .doWrite(data()); EasyExcel.read(file.getPath()).head(ParameterData.class).registerReadListener(new ParameterDataListener()) .sheet().doRead(); } - private void readAndWrite4() throws Exception { - EasyExcel.write(new FileOutputStream(file), ParameterData.class).sheet().doWrite(data()); + private void readAndWrite4(File file, ExcelTypeEnum type) throws Exception { + EasyExcel.write(new FileOutputStream(file), ParameterData.class).excelType(type).sheet().doWrite(data()); EasyExcel.read(file.getPath(), new ParameterDataListener()).head(ParameterData.class).sheet().doRead(); } - private void readAndWrite5() throws Exception { + private void readAndWrite5(File file, ExcelTypeEnum type) throws Exception { ExcelWriter excelWriter = - EasyExcel.write(new FileOutputStream(file)).head(ParameterData.class).relativeHeadRowIndex(0).build(); + EasyExcel.write(new FileOutputStream(file)).excelType(type).head(ParameterData.class).relativeHeadRowIndex( + 0).build(); WriteSheet writeSheet = EasyExcel.writerSheet(0).relativeHeadRowIndex(0).needHead(Boolean.FALSE).build(); WriteTable writeTable = EasyExcel.writerTable(0).relativeHeadRowIndex(0).needHead(Boolean.TRUE).build(); excelWriter.write(data(), writeSheet, writeTable); @@ -88,9 +103,10 @@ public class ParameterDataTest { excelReader.finish(); } - private void readAndWrite6() throws Exception { + private void readAndWrite6(File file, ExcelTypeEnum type) throws Exception { ExcelWriter excelWriter = - EasyExcel.write(new FileOutputStream(file)).head(ParameterData.class).relativeHeadRowIndex(0).build(); + EasyExcel.write(new FileOutputStream(file)).excelType(type).head(ParameterData.class).relativeHeadRowIndex( + 0).build(); WriteSheet writeSheet = EasyExcel.writerSheet(0).relativeHeadRowIndex(0).needHead(Boolean.FALSE).build(); WriteTable writeTable = EasyExcel.writerTable(0).registerConverter(new StringStringConverter()) .relativeHeadRowIndex(0).needHead(Boolean.TRUE).build(); @@ -110,7 +126,7 @@ public class ParameterDataTest { excelReader.finish(); } - private void readAndWrite7() { + private void readAndWrite7(File file, ExcelTypeEnum type) { EasyExcel.write(file, ParameterData.class).registerConverter(new StringStringConverter()).sheet() .registerConverter(new StringStringConverter()).needHead(Boolean.FALSE).table(0).needHead(Boolean.TRUE) .doWrite(data()); @@ -119,7 +135,7 @@ public class ParameterDataTest { } private List data() { - List list = new ArrayList(); + List list = new ArrayList<>(); for (int i = 0; i < 10; i++) { ParameterData simpleData = new ParameterData(); simpleData.setName("姓名" + i); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/repetition/RepetitionDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/repetition/RepetitionDataTest.java index 4c0d8aad..70acf19f 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/repetition/RepetitionDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/repetition/RepetitionDataTest.java @@ -4,11 +4,6 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelReader; @@ -17,8 +12,12 @@ import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** - * * @author Jiaju Zhuang */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -26,15 +25,19 @@ public class RepetitionDataTest { private static File file07; private static File file03; + private static File fileCsv; private static File fileTable07; private static File fileTable03; + private static File fileTableCsv; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("repetition07.xlsx"); file03 = TestFileUtil.createNewFile("repetition03.xls"); + fileCsv = TestFileUtil.createNewFile("repetitionCsv.csv"); fileTable07 = TestFileUtil.createNewFile("repetitionTable07.xlsx"); fileTable03 = TestFileUtil.createNewFile("repetitionTable03.xls"); + fileTableCsv = TestFileUtil.createNewFile("repetitionTableCsv.csv"); } @Test @@ -47,6 +50,11 @@ public class RepetitionDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) { ExcelWriter excelWriter = EasyExcel.write(file, RepetitionData.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet(0).build(); @@ -57,15 +65,20 @@ public class RepetitionDataTest { } @Test - public void t03ReadAndWriteTable07() { + public void t11ReadAndWriteTable07() { readAndWriteTable(fileTable07); } @Test - public void t04ReadAndWriteTable03() { + public void t12ReadAndWriteTable03() { readAndWriteTable(fileTable03); } + @Test + public void t13ReadAndWriteTableCsv() { + readAndWriteTable(fileTableCsv); + } + private void readAndWriteTable(File file) { ExcelWriter excelWriter = EasyExcel.write(file, RepetitionData.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet(0).build(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataTest.java index 2d3c75b6..a381ec43 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataTest.java @@ -4,17 +4,16 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; - /** - * * @author Jiaju Zhuang */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -22,11 +21,13 @@ public class SimpleDataTest { private static File file07; private static File file03; + private static File fileCsv; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("simple07.xlsx"); file03 = TestFileUtil.createNewFile("simple03.xls"); + fileCsv = TestFileUtil.createNewFile("simpleCsv.csv"); } @Test @@ -39,21 +40,31 @@ public class SimpleDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() { + readAndWrite(fileCsv); + } + private void readAndWrite(File file) { EasyExcel.write(file, SimpleData.class).sheet().doWrite(data()); EasyExcel.read(file, SimpleData.class, new SimpleDataListener()).sheet().doRead(); } @Test - public void t03SynchronousRead07() { + public void t11SynchronousRead07() { synchronousRead(file07); } @Test - public void t04SynchronousRead03() { + public void t12SynchronousRead03() { synchronousRead(file03); } + @Test + public void t13SynchronousReadCsv() { + synchronousRead(fileCsv); + } + @Test public void t05SheetNameRead07() { EasyExcel.read(TestFileUtil.readFile("simple" + File.separator + "simple07.xlsx"), SimpleData.class, diff --git a/src/test/java/com/alibaba/easyexcel/test/core/skip/SkipDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/skip/SkipDataTest.java index 3f62994e..ed9e84df 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/skip/SkipDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/skip/SkipDataTest.java @@ -4,23 +4,22 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; - import com.alibaba.easyexcel.test.core.simple.SimpleData; -import com.alibaba.easyexcel.test.core.simple.SimpleDataListener; -import com.alibaba.easyexcel.test.core.simple.SimpleDataSheetNameListener; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelReader; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.event.SyncReadListener; +import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.write.metadata.WriteSheet; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** * @author Jiaju Zhuang */ @@ -29,11 +28,13 @@ public class SkipDataTest { private static File file07; private static File file03; + private static File fileCsv; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("skip.xlsx"); file03 = TestFileUtil.createNewFile("skip.xls"); + fileCsv = TestFileUtil.createNewFile("skip.csv"); } @Test @@ -46,6 +47,11 @@ public class SkipDataTest { readAndWrite(file03); } + @Test + public void t03ReadAndWriteCsv() { + Assert.assertThrows(ExcelGenerateException.class, () -> readAndWrite(fileCsv)); + } + private void readAndWrite(File file) { ExcelWriter excelWriter = EasyExcel.write(file, SimpleData.class).build(); WriteSheet writeSheet0 = EasyExcel.writerSheet(0, "第一个").build(); @@ -70,12 +76,11 @@ public class SkipDataTest { excelReader.read(readSheet1, readSheet3); List syncList = syncReadListener.getList(); Assert.assertEquals(2, syncList.size()); - Assert.assertEquals("name2", ((SkipData) syncList.get(0)).getName()); - Assert.assertEquals("name4", ((SkipData) syncList.get(1)).getName()); + Assert.assertEquals("name2", ((SkipData)syncList.get(0)).getName()); + Assert.assertEquals("name4", ((SkipData)syncList.get(1)).getName()); excelReader.finish(); } - private List data(String name) { List list = new ArrayList(); SkipData data = new SkipData(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/sort/SortDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/sort/SortDataTest.java index 698078a1..f1a2b618 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/sort/SortDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/sort/SortDataTest.java @@ -6,15 +6,15 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; - /** * @author Jiaju Zhuang */ @@ -23,15 +23,19 @@ public class SortDataTest { private static File file07; private static File file03; + private static File fileCsv; private static File sortNoHead07; private static File sortNoHead03; + private static File sortNoHeadCsv; @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("sort.xlsx"); file03 = TestFileUtil.createNewFile("sort.xls"); + fileCsv = TestFileUtil.createNewFile("sort.csv"); sortNoHead07 = TestFileUtil.createNewFile("sortNoHead.xlsx"); sortNoHead03 = TestFileUtil.createNewFile("sortNoHead.xls"); + sortNoHeadCsv = TestFileUtil.createNewFile("sortNoHead.csv"); } @Test @@ -45,15 +49,24 @@ public class SortDataTest { } @Test - public void t03ReadAndWriteNoHead07() { + public void t03ReadAndWriteCsv() { + readAndWrite(fileCsv); + } + + @Test + public void t11ReadAndWriteNoHead07() { readAndWriteNoHead(sortNoHead07); } @Test - public void t04ReadAndWriteNoHead03() { + public void t12ReadAndWriteNoHead03() { readAndWriteNoHead(sortNoHead03); } + @Test + public void t13ReadAndWriteNoHeadCsv() { + readAndWriteNoHead(sortNoHeadCsv); + } private void readAndWrite(File file) { EasyExcel.write(file, SortData.class).sheet().doWrite(data()); @@ -95,7 +108,6 @@ public class SortDataTest { return head; } - private List data() { List list = new ArrayList(); SortData sortData = new SortData(); diff --git a/src/test/java/com/alibaba/easyexcel/test/core/style/StyleData.java b/src/test/java/com/alibaba/easyexcel/test/core/style/StyleData.java index f7094ebb..cc30893e 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/style/StyleData.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/style/StyleData.java @@ -1,6 +1,8 @@ package com.alibaba.easyexcel.test.core.style; import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.HeadFontStyle; +import com.alibaba.excel.annotation.write.style.HeadStyle; import lombok.Data; @@ -8,6 +10,8 @@ import lombok.Data; * @author Jiaju Zhuang */ @Data +@HeadStyle +@HeadFontStyle public class StyleData { @ExcelProperty("字符串") private String string; diff --git a/src/test/java/com/alibaba/easyexcel/test/core/style/StyleDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/style/StyleDataTest.java index 4e170944..ceb571db 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/style/StyleDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/style/StyleDataTest.java @@ -4,20 +4,14 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; - import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.annotation.write.style.HeadFontStyle; +import com.alibaba.excel.annotation.write.style.HeadStyle; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.property.FontProperty; +import com.alibaba.excel.metadata.property.StyleProperty; +import com.alibaba.excel.metadata.data.DataFormatData; import com.alibaba.excel.write.merge.LoopMergeStrategy; import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.excel.write.metadata.style.WriteCellStyle; @@ -27,8 +21,18 @@ import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + /** - * * @author Jiaju Zhuang */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -60,7 +64,9 @@ public class StyleDataTest { protected WriteCellStyle headCellStyle(Head head) { WriteCellStyle writeCellStyle = new WriteCellStyle(); writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); - writeCellStyle.setDataFormat((short)0); + DataFormatData dataFormatData = new DataFormatData(); + dataFormatData.setIndex((short)0); + writeCellStyle.setDataFormatData(dataFormatData); writeCellStyle.setHidden(false); writeCellStyle.setLocked(true); writeCellStyle.setQuotePrefix(true); @@ -110,9 +116,48 @@ public class StyleDataTest { EasyExcel.write(file07, StyleData.class).registerWriteHandler(verticalCellStyleStrategy).sheet() .doWrite(data()); } + @Test + public void t04AbstractVerticalCellStyleStrategy02() { + final StyleProperty styleProperty = StyleProperty.build(StyleData.class.getAnnotation(HeadStyle.class)); + final FontProperty fontProperty = FontProperty.build(StyleData.class.getAnnotation(HeadFontStyle.class)); + AbstractVerticalCellStyleStrategy verticalCellStyleStrategy = new AbstractVerticalCellStyleStrategy() { + @Override + protected WriteCellStyle headCellStyle(Head head) { + WriteCellStyle writeCellStyle = WriteCellStyle.build(styleProperty, fontProperty); + + if (head.getColumnIndex() == 0) { + writeCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); + WriteFont writeFont = new WriteFont(); + writeFont.setItalic(true); + writeFont.setStrikeout(true); + writeFont.setTypeOffset(Font.SS_NONE); + writeFont.setUnderline(Font.U_DOUBLE); + writeFont.setBold(true); + writeFont.setCharset((int)Font.DEFAULT_CHARSET); + } else { + writeCellStyle.setFillForegroundColor(IndexedColors.BLUE.getIndex()); + } + return writeCellStyle; + } + + @Override + protected WriteCellStyle contentCellStyle(Head head) { + WriteCellStyle writeCellStyle = new WriteCellStyle(); + writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); + if (head.getColumnIndex() == 0) { + writeCellStyle.setFillForegroundColor(IndexedColors.DARK_GREEN.getIndex()); + } else { + writeCellStyle.setFillForegroundColor(IndexedColors.PINK.getIndex()); + } + return writeCellStyle; + } + }; + EasyExcel.write(file07, StyleData.class).registerWriteHandler(verticalCellStyleStrategy).sheet() + .doWrite(data()); + } @Test - public void t04LoopMergeStrategy() { + public void t05LoopMergeStrategy() { EasyExcel.write(file07, StyleData.class).sheet().registerWriteHandler(new LoopMergeStrategy(2, 1)) .doWrite(data10()); } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/template/TemplateDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/template/TemplateDataTest.java index adf63137..d6ebd0aa 100644 --- a/src/test/java/com/alibaba/easyexcel/test/core/template/TemplateDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/core/template/TemplateDataTest.java @@ -4,14 +4,14 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; - /** * * @author Jiaju Zhuang @@ -22,6 +22,7 @@ public class TemplateDataTest { private static File file07; private static File file03; + @BeforeClass public static void init() { file07 = TestFileUtil.createNewFile("template07.xlsx"); diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java index 7a0e92e5..309e410f 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java @@ -2,13 +2,11 @@ package com.alibaba.easyexcel.test.demo.fill; import java.io.File; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -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; @@ -17,11 +15,14 @@ import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.fill.FillConfig; import com.alibaba.excel.write.metadata.fill.FillWrapper; +import org.junit.Ignore; +import org.junit.Test; + /** * 写的填充写法 * - * @since 2.1.1 * @author Jiaju Zhuang + * @since 2.1.1 */ @Ignore public class FillTest { @@ -70,7 +71,18 @@ public class FillTest { // 这里 会填充到第一个sheet, 然后文件流会自动关闭 EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(data()); - // 方案2 分多次 填充 会使用文件缓存(省内存) + // 方案2 分多次 填充 会使用文件缓存(省内存) jdk8 + // since: 3.0.0-beta1 + fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx"; + EasyExcel.write(fileName) + .withTemplate(templateFileName) + .sheet() + .doFill(() -> { + // 分页查询数据 + return data(); + }); + + // 方案3 分多次 填充 会使用文件缓存(省内存) fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx"; ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); @@ -205,7 +217,9 @@ public class FillTest { excelWriter.fill(new FillWrapper("data3", data()), writeSheet); Map map = new HashMap(); - map.put("date", "2019年10月9日13:28:28"); + //map.put("date", "2019年10月9日13:28:28"); + map.put("date", new Date()); + excelWriter.fill(map, writeSheet); // 别忘记关闭流 diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataDemoHeadDataListener.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataDemoHeadDataListener.java index 896cea62..53e0bf68 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataDemoHeadDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataDemoHeadDataListener.java @@ -2,14 +2,12 @@ package com.alibaba.easyexcel.test.demo.read; import java.util.ArrayList; import java.util.List; -import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.excel.metadata.CellData; import com.alibaba.fastjson.JSON; /** diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataReadDemoData.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataReadDemoData.java index f5d01e0c..357dbfe9 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataReadDemoData.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/CellDataReadDemoData.java @@ -2,7 +2,7 @@ package com.alibaba.easyexcel.test.demo.read; import java.util.Date; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.CellData; import lombok.Data; diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/CustomStringStringConverter.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/CustomStringStringConverter.java index 5201e750..406b2896 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/CustomStringStringConverter.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/CustomStringStringConverter.java @@ -2,8 +2,9 @@ package com.alibaba.easyexcel.test.demo.read; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -13,7 +14,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; */ public class CustomStringStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String.class; } @@ -34,7 +35,7 @@ public class CustomStringStringConverter implements Converter { * @return */ @Override - public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public String convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return "自定义:" + cellData.getStringValue(); } @@ -51,9 +52,9 @@ public class CustomStringStringConverter implements Converter { * @return */ @Override - public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData(value); + return new WriteCellData<>(value); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java index f26ff4be..6cc1ecef 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoDataListener.java @@ -3,13 +3,13 @@ package com.alibaba.easyexcel.test.demo.read; import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.fastjson.JSON; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * 模板的读取类 * @@ -21,8 +21,11 @@ public class DemoDataListener extends AnalysisEventListener { /** * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 */ - private static final int BATCH_COUNT = 5; - List list = new ArrayList(); + private static final int BATCH_COUNT = 3000; + /** + * 缓存的数据 + */ + private List list = new ArrayList<>(BATCH_COUNT); /** * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 */ @@ -45,8 +48,7 @@ public class DemoDataListener extends AnalysisEventListener { /** * 这个每一条数据解析都会来调用 * - * @param data - * one row value. Is is same as {@link AnalysisContext#readRowHolder()} + * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} * @param context */ @Override @@ -57,7 +59,7 @@ public class DemoDataListener extends AnalysisEventListener { if (list.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list - list.clear(); + list = new ArrayList<>(BATCH_COUNT); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExtraListener.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExtraListener.java index 01adfe72..df2afc36 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExtraListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/DemoExtraListener.java @@ -1,19 +1,18 @@ package com.alibaba.easyexcel.test.demo.read; -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.metadata.CellExtra; import com.alibaba.fastjson.JSON; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * 读取单元格的批注 * - * @author: kaiux - * @date: 2019-10-23 14:10 + * @author Jiaju Zhuang **/ public class DemoExtraListener extends AnalysisEventListener { private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class); diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java index ea011b31..ea447719 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java @@ -1,25 +1,29 @@ package com.alibaba.easyexcel.test.demo.read; import java.io.File; +import java.util.ArrayList; 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.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.fastjson.JSON; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * 读的常见写法 * @@ -41,18 +45,70 @@ public class ReadTest { */ @Test public void simpleRead() { - // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 - // 写法1: + // 写法1:JDK8+ ,不用额外写一个DemoDataListener + // since: 3.0.0-beta1 String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 - EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead(); + // 这里每次会读取3000条数据 然后返回过来 直接调用使用数据就行 + EasyExcel.read(fileName, DemoData.class, new PageReadListener(dataList -> { + for (DemoData demoData : dataList) { + LOGGER.info("读取到一条数据{}", JSON.toJSONString(demoData)); + } + })).sheet().doRead(); // 写法2: + // 匿名内部类 不用额外写一个DemoDataListener + fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; + // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 + EasyExcel.read(fileName, DemoData.class, new ReadListener() { + /** + * 单次缓存的数据量 + */ + public static final int BATCH_COUNT = 3000; + /** + *临时存储 + */ + private List cachedData = new ArrayList<>(BATCH_COUNT); + + @Override + public void invoke(DemoData data, AnalysisContext context) { + cachedData.add(data); + if (cachedData.size() >= BATCH_COUNT) { + saveData(); + // 存储完成清理 list + cachedData = new ArrayList<>(BATCH_COUNT); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + saveData(); + } + + /** + * 加上存储数据库 + */ + private void saveData() { + LOGGER.info("{}条数据,开始存储数据库!", cachedData.size()); + LOGGER.info("存储数据库成功!"); + } + }).sheet().doRead(); + + // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 + // 写法3: + fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; + // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 + EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead(); + + // 写法4: fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; + // 一个文件一个reader ExcelReader excelReader = null; try { excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build(); + // 构建一个sheet 这里可以指定名字或者no ReadSheet readSheet = EasyExcel.readSheet(0).build(); + // 读取一个sheet excelReader.read(readSheet); } finally { if (excelReader != null) { diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java index ab0ad968..af2dfce5 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java @@ -10,6 +10,9 @@ import java.util.Map; import javax.servlet.http.HttpServletResponse; +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -17,9 +20,6 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; -import com.alibaba.excel.EasyExcel; -import com.alibaba.fastjson.JSON; - /** * web读写案例 * @@ -43,12 +43,18 @@ public class WebTest { @GetMapping("download") public void download(HttpServletResponse response) throws IOException { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman - response.setContentType("application/vnd.ms-excel"); + response.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()); + + ArrayList> list = new ArrayList<>(); + ArrayList sublist = new ArrayList(); + sublist.add("t1"); + sublist.add("t2"); + list.add(sublist); + EasyExcel.write(response.getOutputStream()).sheet("模板").doWrite(list); } /** @@ -60,7 +66,7 @@ public class WebTest { public void downloadFailedUsingJson(HttpServletResponse response) throws IOException { // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman try { - response.setContentType("application/vnd.ms-excel"); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20"); diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/CommentWriteHandler.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/CommentWriteHandler.java index 299d4072..d6eacb42 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/CommentWriteHandler.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/CommentWriteHandler.java @@ -8,6 +8,7 @@ import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFRichTextString; import com.alibaba.excel.write.handler.AbstractRowWriteHandler; +import com.alibaba.excel.write.handler.RowWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; @@ -16,7 +17,7 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder; * * @author Jiaju Zhuang */ -public class CommentWriteHandler extends AbstractRowWriteHandler { +public class CommentWriteHandler implements RowWriteHandler { @Override public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java index b1bcb7dc..960eda40 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomCellWriteHandler.java @@ -2,6 +2,12 @@ package com.alibaba.easyexcel.test.demo.write; import java.util.List; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; + import org.apache.poi.common.usermodel.HyperlinkType; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CreationHelper; @@ -9,24 +15,18 @@ import org.apache.poi.ss.usermodel.Hyperlink; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.excel.metadata.CellData; -import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.write.handler.AbstractCellWriteHandler; -import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteTableHolder; - /** * 自定义拦截器。对第一行第一列的头超链接到:https://github.com/alibaba/easyexcel * * @author Jiaju Zhuang */ -public class CustomCellWriteHandler extends AbstractCellWriteHandler { +public class CustomCellWriteHandler implements CellWriteHandler { private static final Logger LOGGER = LoggerFactory.getLogger(CustomCellWriteHandler.class); @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, - List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { + List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { // 这里可以对cell进行任何操作 LOGGER.info("第{}行,第{}列写入完成。", cell.getRowIndex(), cell.getColumnIndex()); if (isHead && cell.getColumnIndex() == 0) { diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomStringStringConverter.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomStringStringConverter.java index 45ebc8c1..5ea599be 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomStringStringConverter.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/CustomStringStringConverter.java @@ -2,8 +2,9 @@ package com.alibaba.easyexcel.test.demo.write; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.property.ExcelContentProperty; /** @@ -13,7 +14,7 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty; */ public class CustomStringStringConverter implements Converter { @Override - public Class supportJavaTypeKey() { + public Class supportJavaTypeKey() { return String.class; } @@ -25,16 +26,13 @@ public class CustomStringStringConverter implements Converter { /** * 这里是读的时候会调用 不用管 * - * @param cellData - * NotNull - * @param contentProperty - * Nullable - * @param globalConfiguration - * NotNull + * @param cellData NotNull + * @param contentProperty Nullable + * @param globalConfiguration NotNull * @return */ @Override - public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, + public String convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return cellData.getStringValue(); } @@ -42,18 +40,15 @@ public class CustomStringStringConverter implements Converter { /** * 这里是写的时候会调用 不用管 * - * @param value - * NotNull - * @param contentProperty - * Nullable - * @param globalConfiguration - * NotNull + * @param value NotNull + * @param contentProperty Nullable + * @param globalConfiguration NotNull * @return */ @Override - public CellData convertToExcelData(String value, ExcelContentProperty contentProperty, + public WriteCellData convertToExcelData(String value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { - return new CellData("自定义:" + value); + return new WriteCellData<>("自定义:" + value); } } diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDataWithAnnotation.java similarity index 94% rename from src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java rename to src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDataWithAnnotation.java index 3fcb9484..a7bd7caa 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageData.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDataWithAnnotation.java @@ -14,12 +14,11 @@ import lombok.Data; /** * 图片导出类 * - * @author Jiaju Zhuang */ @Data @ContentRowHeight(100) @ColumnWidth(100 / 8) -public class ImageData { +public class ImageDataWithAnnotation { private File file; private InputStream inputStream; /** diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDemoData.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDemoData.java new file mode 100644 index 00000000..ba80d6f1 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/ImageDemoData.java @@ -0,0 +1,45 @@ +package com.alibaba.easyexcel.test.demo.write; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.converters.string.StringImageConverter; +import com.alibaba.excel.metadata.data.WriteCellData; + +import lombok.Data; + +/** + * 图片导出类 + * + * @author Jiaju Zhuang + */ +@Data +@ContentRowHeight(100) +@ColumnWidth(100 / 8) +public class ImageDemoData { + private File file; + private InputStream inputStream; + /** + * 如果string类型 必须指定转换器,string默认转换成string + */ + @ExcelProperty(converter = StringImageConverter.class) + private String string; + private byte[] byteArray; + /** + * 根据url导出 + * + * @since 2.1.1 + */ + private URL url; + + /** + * 根据文件导出 并设置导出的位置。 + * + * @since 3.0.0-beta1 + */ + private WriteCellData writeCellDataFile; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteCellDemoData.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteCellDemoData.java new file mode 100644 index 00000000..31eeee41 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteCellDemoData.java @@ -0,0 +1,41 @@ +package com.alibaba.easyexcel.test.demo.write; + +import com.alibaba.excel.metadata.data.WriteCellData; + +import lombok.Data; + +/** + * 根据WriteCellData写 + * + * @author Jiaju Zhuang + */ +@Data +public class WriteCellDemoData { + /** + * 超链接 + * + * @since 3.0.0-beta1 + */ + private WriteCellData hyperlink; + + /** + * 备注 + * + * @since 3.0.0-beta1 + */ + private WriteCellData commentData; + + /** + * 公式 + * + * @since 3.0.0-beta1 + */ + private WriteCellData formulaData; + + /** + * 指定单元格的样式。当然样式 也可以用注解等方式。 + * + * @since 3.0.0-beta1 + */ + private WriteCellData writeCellStyle; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java index 4bce5127..852bc280 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java @@ -9,12 +9,6 @@ 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; @@ -24,6 +18,15 @@ 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.CommentData; +import com.alibaba.excel.metadata.data.FormulaData; +import com.alibaba.excel.metadata.data.HyperlinkData; +import com.alibaba.excel.metadata.data.HyperlinkData.HyperlinkType; +import com.alibaba.excel.metadata.data.ImageData; +import com.alibaba.excel.metadata.data.ImageData.ImageType; +import com.alibaba.excel.metadata.data.RichTextStringData; +import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.write.merge.LoopMergeStrategy; import com.alibaba.excel.write.metadata.WriteSheet; @@ -33,6 +36,12 @@ import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +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; + /** * 写的常见写法 * @@ -50,14 +59,26 @@ public class WriteTest { */ @Test public void simpleWrite() { - // 写法1 + // 写法1 JDK8+ + // since: 3.0.0-beta1 String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 - EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data()); + EasyExcel.write(fileName, DemoData.class) + .sheet("模板") + .doWrite(() -> { + // 分页查询数据 + return data(); + }); // 写法2 fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; + // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 + // 如果这里想使用03 则 传入excelType参数即可 + EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data()); + + // 写法3 + fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去写 ExcelWriter excelWriter = null; try { @@ -86,6 +107,7 @@ public class WriteTest { @Test public void excludeOrIncludeWrite() { String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx"; + // 这里需要注意 在使用ExcelProperty注解的使用,如果想不空列则需要加入order字段,而不是index,order会忽略空列,然后继续往后,而index,不会忽略空列,在第几列就是第几列。 // 根据用户传入字段 假设我们要忽略 date Set excludeColumnFiledNames = new HashSet(); @@ -194,7 +216,8 @@ public class WriteTest { excelWriter = EasyExcel.write(fileName).build(); // 去调用写入,这里我调用了五次,实际使用时根据数据库分页的总的页数来。这里最终会写到5个sheet里面 for (int i = 0; i < 5; i++) { - // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class 实际上可以一直变 + // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class + // 实际上可以一直变 WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build(); // 分页去数据库查询数据 这里可以去数据库查询每一页的数据 List data = data(); @@ -227,7 +250,7 @@ public class WriteTest { /** * 图片导出 *

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

* 2. 直接写即可 */ @@ -237,19 +260,68 @@ public class WriteTest { // 如果使用流 记得关闭 InputStream inputStream = null; try { - List list = new ArrayList(); - ImageData imageData = new ImageData(); - list.add(imageData); + List list = new ArrayList<>(); + ImageDemoData imageDemoData = new ImageDemoData(); + list.add(imageDemoData); String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg"; // 放入五种类型的图片 实际使用只要选一种即可 - imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath))); - imageData.setFile(new File(imagePath)); - imageData.setString(imagePath); + imageDemoData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath))); + imageDemoData.setFile(new File(imagePath)); + imageDemoData.setString(imagePath); inputStream = FileUtils.openInputStream(new File(imagePath)); - imageData.setInputStream(inputStream); - imageData.setUrl(new URL( + imageDemoData.setInputStream(inputStream); + imageDemoData.setUrl(new URL( "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg")); - EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list); + + // 这里演示 + // 需要额外放入文字 + // 而且需要放入2个图片 + // 第一个图片靠左 + // 第二个靠右 而且要额外的占用他后面的单元格 + WriteCellData writeCellData = new WriteCellData<>(); + imageDemoData.setWriteCellDataFile(writeCellData); + // 这里可以设置为 EMPTY 则代表不需要其他数据了 + writeCellData.setType(CellDataTypeEnum.STRING); + writeCellData.setStringValue("额外的放一些文字"); + + // 可以放入多个图片 + List imageDataList = new ArrayList<>(); + ImageData imageData = new ImageData(); + imageDataList.add(imageData); + writeCellData.setImageDataList(imageDataList); + // 放入2进制图片 + imageData.setImage(FileUtils.readFileToByteArray(new File(imagePath))); + // 图片类型 + imageData.setImageType(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(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); } finally { if (inputStream != null) { inputStream.close(); @@ -257,6 +329,61 @@ public class WriteTest { } } + /** + * 超链接、备注、公式、指定单个单元格的样式 + *

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

+ * 2. 直接写即可 + */ + @Test + public void writeCellDataWrite() throws Exception { + String fileName = TestFileUtil.getPath() + "writeCellDataWrite" + System.currentTimeMillis() + ".xlsx"; + WriteCellDemoData writeCellDemoData = new WriteCellDemoData(); + + // 设置超链接 + WriteCellData hyperlink = new WriteCellData<>("官方网站"); + writeCellDemoData.setHyperlink(hyperlink); + HyperlinkData hyperlinkData = new HyperlinkData(); + hyperlink.setHyperlinkData(hyperlinkData); + hyperlinkData.setAddress("https://github.com/alibaba/easyexcel"); + hyperlinkData.setHyperlinkType(HyperlinkType.URL); + + // 设置备注 + WriteCellData 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); + + // 设置公式 + WriteCellData formula = new WriteCellData<>(); + writeCellDemoData.setFormulaData(formula); + FormulaData formulaData = new FormulaData(); + formula.setFormulaData(formulaData); + // 将 123456789 中的第一个数字替换成 2 + // 这里只是例子 如果真的涉及到公式 能内存算好尽量内存算好 公式能不用尽量不用 + formulaData.setFormulaValue("REPLACE(123456789,1,1,2)"); + + // 设置单个单元格的样式 当然样式 很多的话 也可以用注解等方式。 + WriteCellData writeCellStyle = new WriteCellData<>("单元格样式"); + writeCellDemoData.setWriteCellStyle(writeCellStyle); + WriteCellStyle writeCellStyleData = new WriteCellStyle(); + writeCellStyle.setWriteCellStyle(writeCellStyleData); + // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色. + writeCellStyleData.setFillPatternType(FillPatternType.SOLID_FOREGROUND); + // 背景绿色 + writeCellStyleData.setFillForegroundColor(IndexedColors.GREEN.getIndex()); + + List data = new ArrayList<>(); + data.add(writeCellDemoData); + EasyExcel.write(fileName, WriteCellDemoData.class).inMemory(true).sheet("模板").doWrite(data); + } + /** * 根据模板写入 *

@@ -325,7 +452,7 @@ public class WriteTest { // 背景设置为红色 headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex()); WriteFont headWriteFont = new WriteFont(); - headWriteFont.setFontHeightInPoints((short) 20); + headWriteFont.setFontHeightInPoints((short)20); headWriteCellStyle.setWriteFont(headWriteFont); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); @@ -335,7 +462,7 @@ public class WriteTest { contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 - contentWriteFont.setFontHeightInPoints((short) 20); + contentWriteFont.setFontHeightInPoints((short)20); contentWriteCellStyle.setWriteFont(contentWriteFont); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 HorizontalCellStyleStrategy horizontalCellStyleStrategy = @@ -428,7 +555,8 @@ public class WriteTest { /** * 自动列宽(不太精确) *

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

* poi 自带{@link SXSSFSheet#autoSizeColumn(int)} 对中文支持也不太好。目前没找到很好的算法。 有的话可以推荐下。 * diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/CamlData.java b/src/test/java/com/alibaba/easyexcel/test/temp/CamlData.java new file mode 100644 index 00000000..9c3f39e4 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/CamlData.java @@ -0,0 +1,18 @@ +package com.alibaba.easyexcel.test.temp; + +import lombok.Data; + +/** + * TODO + * + * @author 是仪 + */ +@Data +public class CamlData { + private String string1; + private String String2; + private String sTring3; + private String STring4; + private String STRING5; + private String STRing6; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index ae2e03fe..3082362a 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -13,10 +13,10 @@ import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.fastjson.JSON; +import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.hssf.util.CellReference; import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.IndexedColors; -import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,19 +26,20 @@ import org.slf4j.LoggerFactory; * * @author Jiaju Zhuang **/ -@Ignore public class Lock2Test { private static final Logger LOGGER = LoggerFactory.getLogger(Lock2Test.class); @Test public void test() throws Exception { -// File file = TestFileUtil.readUserHomeFile("test/test6.xls"); + // File file = TestFileUtil.readUserHomeFile("test/test4.xlsx"); + // File file = TestFileUtil.readUserHomeFile("test/test6.xls"); File file = new File("/Users/zhuangjiaju/IdeaProjects/easyexcel/src/test/resources/converter/converter07.xlsx"); - List list = EasyExcel.read(file).sheet(0).headRowNumber(0).doReadSync(); + List list = EasyExcel.read("/Users/zhuangjiaju/test/test3.xlsx").sheet(0).headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); for (Object data : list) { + LOGGER.info("返回数据:{}", CollectionUtils.size(data)); LOGGER.info("返回数据:{}", JSON.toJSONString(data)); } } @@ -60,7 +61,7 @@ public class Lock2Test { // 背景设置为红色 headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex()); WriteFont headWriteFont = new WriteFont(); - headWriteFont.setFontHeightInPoints((short) 20); + headWriteFont.setFontHeightInPoints((short)20); headWriteCellStyle.setWriteFont(headWriteFont); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); @@ -70,7 +71,7 @@ public class Lock2Test { contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 - contentWriteFont.setFontHeightInPoints((short) 20); + contentWriteFont.setFontHeightInPoints((short)20); contentWriteCellStyle.setWriteFont(contentWriteFont); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 HorizontalCellStyleStrategy horizontalCellStyleStrategy = @@ -81,6 +82,32 @@ public class Lock2Test { .doWrite(data()); } + @Test + public void simpleWrite() { + String fileName = TestFileUtil.getPath() + System.currentTimeMillis() + ".xlsx"; + System.out.println(fileName); + EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList()); + } + + private List> head() { + List> list = new ArrayList>(); + List head0 = new ArrayList(); + head0.add("表头"); + + list.add(head0); + return list; + } + + private List> dataList() { + List> list = new ArrayList>(); + List data = new ArrayList(); + data.add("字符串"); + 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++) { diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java b/src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java index 64cce8db..bda277c6 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/LockDataListener.java @@ -2,7 +2,6 @@ package com.alibaba.easyexcel.test.temp; import java.util.ArrayList; import java.util.List; -import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,7 +9,6 @@ import org.slf4j.LoggerFactory; import com.alibaba.easyexcel.test.demo.read.DemoDataListener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.excel.metadata.CellData; import com.alibaba.fastjson.JSON; /** diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java index ad09717f..031e5114 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java @@ -1,18 +1,17 @@ package com.alibaba.easyexcel.test.temp; -import java.io.File; import java.io.FileInputStream; import java.util.List; import java.util.Map; +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; + import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.excel.EasyExcel; -import com.alibaba.fastjson.JSON; - /** * 临时测试 * @@ -24,9 +23,8 @@ public class LockTest { @Test public void test() throws Exception { - List list = - EasyExcel.read(new FileInputStream("/Users/zhuangjiaju/Downloads/点位配置表 (1).xlsx")).doReadAllSync(); + EasyExcel.read(new FileInputStream("/Users/zhuangjiaju/test/pic.xls")).doReadAllSync(); for (Object data : list) { LOGGER.info("返回数据:{}", JSON.toJSONString(data)); } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java index 008d7629..23f623b6 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/WriteLargeTest.java @@ -3,18 +3,7 @@ package com.alibaba.easyexcel.test.temp; import java.util.ArrayList; import java.util.List; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.easyexcel.test.core.large.LargeData; -import com.alibaba.easyexcel.test.demo.write.DemoData; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; @@ -23,6 +12,13 @@ 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.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * 临时测试 * @@ -59,8 +55,23 @@ public class WriteLargeTest { HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); + ExcelWriter excelWriter = EasyExcel.write(fileName, LargeData.class).registerWriteHandler( + horizontalCellStyleStrategy).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + for (int j = 0; j < 100; j++) { + excelWriter.write(data(), writeSheet); + LOGGER.info("{} fill success.", j); + } + excelWriter.finish(); - ExcelWriter excelWriter = EasyExcel.write(fileName,LargeData.class).registerWriteHandler(horizontalCellStyleStrategy).build(); + } + + @Test + public void test2() throws Exception { + // 方法2 如果写到不同的sheet 同一个对象 + String fileName = TestFileUtil.getPath() + "large" + System.currentTimeMillis() + ".xlsx"; + + ExcelWriter excelWriter = EasyExcel.write(fileName, LargeData.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); for (int j = 0; j < 100; j++) { excelWriter.write(data(), writeSheet); @@ -70,39 +81,17 @@ public class WriteLargeTest { } + private List> data() { + List> list = new ArrayList<>(); - private List data() { - List list = new ArrayList(); - int size = i + 5000; - for (; i < size; i++) { - LargeData largeData = new LargeData(); - list.add(largeData); - largeData.setStr1("str1-" + i); - largeData.setStr2("str2-" + i); - largeData.setStr3("str3-" + i); - largeData.setStr4("str4-" + i); - largeData.setStr5("str5-" + i); - largeData.setStr6("str6-" + i); - largeData.setStr7("str7-" + i); - largeData.setStr8("str8-" + i); - largeData.setStr9("str9-" + i); - largeData.setStr10("str10-" + i); - largeData.setStr11("str11-" + i); - largeData.setStr12("str12-" + i); - largeData.setStr13("str13-" + i); - largeData.setStr14("str14-" + i); - largeData.setStr15("str15-" + i); - largeData.setStr16("str16-" + i); - largeData.setStr17("str17-" + i); - largeData.setStr18("str18-" + i); - largeData.setStr19("str19-" + i); - largeData.setStr20("str20-" + i); - largeData.setStr21("str21-" + i); - largeData.setStr22("str22-" + i); - largeData.setStr23("str23-" + i); - largeData.setStr24("str24-" + i); - largeData.setStr25("str25-" + i); + for (int j = 0; j < 10000; j++) { + List oneRow = new ArrayList<>(); + for (int i = 0; i < 150; i++) { + oneRow.add("这是测试字段" + i); + } + list.add(oneRow); } + return list; } } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java index f8db7f9c..f3f96810 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/WriteV33Test.java @@ -1,28 +1,26 @@ package com.alibaba.easyexcel.test.temp; -import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.alibaba.easyexcel.test.demo.write.DemoData; +import com.alibaba.easyexcel.test.demo.write.IndexData; +import com.alibaba.easyexcel.test.temp.data.DataType; +import com.alibaba.easyexcel.test.temp.data.HeadType; 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.write.merge.OnceAbsoluteMergeStrategy; 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 com.alibaba.fastjson.JSON; + +import lombok.Data; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * 临时测试 @@ -41,7 +39,8 @@ public class WriteV33Test { OnceAbsoluteMergeStrategy onceAbsoluteMergeStrategy = new OnceAbsoluteMergeStrategy(2, 2, 0, 1); // 这里 指定文件 - ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).registerWriteHandler(onceAbsoluteMergeStrategy).build(); + ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).registerWriteHandler( + onceAbsoluteMergeStrategy).build(); WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "模板1").build(); WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "模板2").build(); WriteSheet writeSheet3 = EasyExcel.writerSheet(3, "模板3").build(); @@ -64,4 +63,65 @@ public class WriteV33Test { return list; } + @Test + public void test33() throws Exception { + List data = getData(); + String fileName = TestFileUtil.getPath() + "repeatedWrite" + System.currentTimeMillis() + ".xlsx"; + + ExcelWriter excelWriter = null; + excelWriter = EasyExcel.write(fileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet(1, "test") + .head(HeadType.class) + .build(); + excelWriter.write(data, writeSheet); + excelWriter.finish(); + } + + private List getData() { + DataType vo = new DataType(); + vo.setId(738); + vo.setFirstRemark("1222"); + vo.setSecRemark("22222"); + return Collections.singletonList(vo); + } + + @Test + public void indexWrite() { + String fileName = TestFileUtil.getPath() + "indexWrite" + System.currentTimeMillis() + ".xlsx"; + + Man man = new Man(); + man.setAddr("武汉"); + man.setName("张三"); + ExcelWriter excelWriter = EasyExcel.write(fileName, Humen.class).build(); + WriteSheet writeSheet = EasyExcel.writerSheet("test").build(); + excelWriter.write(Collections.singletonList(man), writeSheet); + // 千万别忘记finish 会帮忙关闭流 + excelWriter.finish(); + } + + private List indexData() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + IndexData data = new IndexData(); + data.setString("字符串" + i); + data.setDate(new Date()); + data.setDoubleData(0.56); + list.add(data); + } + return list; + } + + @Data + static class Humen{ + @ExcelProperty("名字") + private String name; + } + + @Data + static + class Man extends Humen{ + @ExcelProperty("地址") + private String addr; + } + } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Xls03Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Xls03Test.java index c4331b1e..906c092e 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Xls03Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Xls03Test.java @@ -2,15 +2,17 @@ package com.alibaba.easyexcel.test.temp; import java.util.List; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.util.BeanMapUtils; +import com.alibaba.fastjson.JSON; + +import net.sf.cglib.beans.BeanMap; +import net.sf.cglib.core.DebuggingClassWriter; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.EasyExcel; -import com.alibaba.fastjson.JSON; - /** * 临时测试 * @@ -27,4 +29,24 @@ public class Xls03Test { LOGGER.info("返回数据:{}", JSON.toJSONString(data)); } } + + @Test + public void test2() { + System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); + System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, + "/Users/zhuangjiaju/IdeaProjects/easyexcel/target"); + + CamlData camlData = new CamlData(); + //camlData.setTest("test2"); + //camlData.setAEst("test3"); + //camlData.setTEST("test4"); + + BeanMap beanMap = BeanMapUtils.create(camlData); + + LOGGER.info("test:{}", beanMap.get("test")); + LOGGER.info("test:{}", beanMap.get("Test")); + LOGGER.info("test:{}", beanMap.get("TEst")); + LOGGER.info("test:{}", beanMap.get("TEST")); + + } } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/bug/DataType.java b/src/test/java/com/alibaba/easyexcel/test/temp/bug/DataType.java new file mode 100644 index 00000000..37b8dc2b --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/bug/DataType.java @@ -0,0 +1,33 @@ +package com.alibaba.easyexcel.test.temp.bug; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * @author jiaosong + * @desc + * @date 2021/4/6 + */ +@Data +public class DataType { + /** + * 任务id + */ + @ExcelProperty("任务ID") + private Integer id; + + @ExcelProperty("多余字段1") + private String firstSurplus; + + @ExcelProperty("多余字段2") + private String secSurplus; + + @ExcelProperty("多余字段3") + private String thirdSurplus; + + @ExcelProperty(value = "备注1") + private String firstRemark; + + @ExcelProperty(value = "备注2") + private String secRemark; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/bug/ExcelCreat.java b/src/test/java/com/alibaba/easyexcel/test/temp/bug/ExcelCreat.java new file mode 100644 index 00000000..f9d97463 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/bug/ExcelCreat.java @@ -0,0 +1,38 @@ +package com.alibaba.easyexcel.test.temp.bug; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.util.Collections; +import java.util.List; + +/** + * @author jiaosong + * @desc + * @date 2020/4/6 + */ +public class ExcelCreat { + + + public static void main(String[] args) throws FileNotFoundException { + List data = getData(); + ExcelWriter excelWriter = null; + excelWriter = EasyExcel.write(new FileOutputStream("all.xlsx")).build(); + WriteSheet writeSheet = EasyExcel.writerSheet(1, "test") + .head(HeadType.class) + .build(); + excelWriter.write(data, writeSheet); + excelWriter.finish(); + } + + private static List getData() { + DataType vo = new DataType(); + vo.setId(738); + vo.setFirstRemark("1222"); + vo.setSecRemark("22222"); + return Collections.singletonList(vo); + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/bug/HeadType.java b/src/test/java/com/alibaba/easyexcel/test/temp/bug/HeadType.java new file mode 100644 index 00000000..15ee006d --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/bug/HeadType.java @@ -0,0 +1,28 @@ +package com.alibaba.easyexcel.test.temp.bug; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * @author jiaosong + * @desc + * @date 2021/4/6 + */ +@Data +public class HeadType { + + + /** + * 任务id + */ + @ExcelProperty("任务ID") + private Integer id; + + + @ExcelProperty(value = "备注1") + private String firstRemark; + + @ExcelProperty(value = "备注2") + private String secRemark; + +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvData.java b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvData.java new file mode 100644 index 00000000..2f645339 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvData.java @@ -0,0 +1,28 @@ +package com.alibaba.easyexcel.test.temp.csv; + +import java.util.Date; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +@Data +public class CsvData { + @ExcelProperty("字符串标题") + private String string; + @ExcelProperty("日期标题") + private Date date; + @ExcelProperty("数字标题") + private Double doubleData; + /** + * 忽略这个字段 + */ + @ExcelIgnore + private String ignore; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvDataListeer.java b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvDataListeer.java new file mode 100644 index 00000000..e3fdd695 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvDataListeer.java @@ -0,0 +1,20 @@ +package com.alibaba.easyexcel.test.temp.csv; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.fastjson.JSON; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CsvDataListeer extends AnalysisEventListener { + @Override + public void invoke(CsvData data, AnalysisContext context) { + log.info("data:{}", JSON.toJSONString(data)); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java new file mode 100644 index 00000000..91293019 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java @@ -0,0 +1,112 @@ +package com.alibaba.easyexcel.test.temp.csv; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; +import org.apache.poi.poifs.filesystem.FileMagic; +import org.junit.Ignore; +import org.junit.Test; + +@Ignore +@Slf4j +public class CsvReadTest { + + @Test + public void write() throws Exception { + Appendable out = new PrintWriter( + new OutputStreamWriter(new FileOutputStream(TestFileUtil.createNewFile("csvWrite1.csv")))); + CSVPrinter printer = CSVFormat.DEFAULT.withHeader("userId", "userName") + .print(out); + for (int i = 0; i < 10; i++) { + printer.printRecord("userId" + i, "userName" + i); + } + printer.flush(); + printer.close(); + } + + @Test + public void read1() throws Exception { + Iterable records = CSVFormat.DEFAULT.withNullString("").parse( + new FileReader("/Users/zhuangjiaju/IdeaProjects/easyexcel/target/test-classes/t1.csv")); + for (CSVRecord record : records) { + String lastName = record.get(0); + String firstName = record.get(1); + log.info("row:{},{}", lastName, firstName); + } + + } + + @Test + public void csvWrite() throws Exception { + // 写法1 + String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".csv"; + // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 + // 如果这里想使用03 则 传入excelType参数即可 + EasyExcel.write(fileName, CsvData.class).sheet().doWrite(data()); + + // 读 + List list = EasyExcel.read(fileName).sheet(0).headRowNumber(0).doReadSync(); + log.info("数据:{}", list.size()); + for (Object data : list) { + log.info("返回数据:{}", JSON.toJSONString(data)); + } + } + + @Test + public void writev2() throws Exception { + // 写法1 + String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".csv"; + // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 + // 如果这里想使用03 则 传入excelType参数即可 + EasyExcel.write(fileName, CsvData.class).sheet().doWrite(data()); + + EasyExcel.read(fileName, CsvData.class, new CsvDataListeer()).sheet().doRead(); + } + + @Test + public void writeFile() throws Exception { + FileInputStream fileInputStream = new FileInputStream(new File("/Users/zhuangjiaju/test/test1.csv")); + FileMagic fileMagic = FileMagic.valueOf(fileInputStream); + log.info("{}", fileMagic); + } + + private List data() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + CsvData data = new CsvData(); + data.setString("字符,串" + i); + //data.setDate(new Date()); + data.setDoubleData(0.56); + data.setIgnore("忽略" + i); + list.add(data); + } + return list; + } + + @Test + public void read() { + // + //Iterable records = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(in); + //for (CSVRecord record : records) { + // String lastName = record.get("id"); + // String firstName = record.get("name"); + // System.out.println(lastName); + // System.out.println(firstName); + //} + + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/data/DataType.java b/src/test/java/com/alibaba/easyexcel/test/temp/data/DataType.java new file mode 100644 index 00000000..8a4b1fb7 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/data/DataType.java @@ -0,0 +1,29 @@ +package com.alibaba.easyexcel.test.temp.data; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +@Data +public class DataType { + /** + * 任务id + */ + @ExcelProperty("任务ID") + private Integer id; + + @ExcelProperty("多余字段1") + private String firstSurplus; + + @ExcelProperty("多余字段2") + private String secSurplus; + + @ExcelProperty("多余字段3") + private String thirdSurplus; + + @ExcelProperty(value = "备注1") + private String firstRemark; + + @ExcelProperty(value = "备注2") + private String secRemark; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/data/HeadType.java b/src/test/java/com/alibaba/easyexcel/test/temp/data/HeadType.java new file mode 100644 index 00000000..32bd065e --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/data/HeadType.java @@ -0,0 +1,24 @@ +package com.alibaba.easyexcel.test.temp.data; + +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +@Data +public class HeadType { + + + /** + * 任务id + */ + @ExcelProperty("任务ID") + private Integer id; + + + @ExcelProperty(value = "备注1") + private String firstRemark; + + @ExcelProperty(value = "备注2") + private String secRemark; + +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatData.java b/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatData.java index d057d8e7..86303729 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatData.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatData.java @@ -1,6 +1,7 @@ package com.alibaba.easyexcel.test.temp.dataformat; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; import lombok.Data; @@ -11,6 +12,6 @@ import lombok.Data; **/ @Data public class DataFormatData { - private CellData date; - private CellData num; + private ReadCellData date; + private ReadCellData num; } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatTest.java index e165d987..4440f350 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatTest.java @@ -9,6 +9,12 @@ import java.util.List; import java.util.Locale; import java.util.regex.Pattern; +import com.alibaba.easyexcel.test.core.dataformat.DateFormatData; +import com.alibaba.easyexcel.test.temp.Lock2Test; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; + import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DataFormatter; @@ -21,12 +27,6 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.easyexcel.test.core.dataformat.DateFormatData; -import com.alibaba.easyexcel.test.temp.Lock2Test; -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; -import com.alibaba.fastjson.JSON; - /** * 格式测试 * @@ -44,9 +44,9 @@ public class DataFormatTest { EasyExcel.read(file, DataFormatData.class, null).sheet().headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); for (DataFormatData data : list) { - Integer dataFormat = data.getDate().getDataFormat(); + Short dataFormat = data.getDate().getDataFormatData().getIndex(); - String dataFormatString = data.getDate().getDataFormatString(); + String dataFormatString = data.getDate().getFormulaData().getFormulaValue(); if (dataFormat == null || dataFormatString == null) { @@ -67,9 +67,9 @@ public class DataFormatTest { EasyExcel.read(file, DataFormatData.class, null).sheet().headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); for (DataFormatData data : list) { - Integer dataFormat = data.getDate().getDataFormat(); + Short dataFormat = data.getDate().getDataFormatData().getIndex(); - String dataFormatString = data.getDate().getDataFormatString(); + String dataFormatString = data.getDate().getFormulaData().getFormulaValue(); if (dataFormat == null || dataFormatString == null) { diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatter1.java b/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatter1.java index 0239ed5b..c4dce8d3 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatter1.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/dataformat/DataFormatter1.java @@ -968,12 +968,12 @@ public class DataFormatter1 implements Observer { return ""; } - CellType cellType = cell.getCellTypeEnum(); + CellType cellType = cell.getCellType(); if (cellType == CellType.FORMULA) { if (evaluator == null) { return cell.getCellFormula(); } - cellType = evaluator.evaluateFormulaCellEnum(cell); + cellType = evaluator.evaluateFormulaCell(cell); } switch (cellType) { case NUMERIC: diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/fill/FillTempTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/fill/FillTempTest.java new file mode 100644 index 00000000..2c201863 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/fill/FillTempTest.java @@ -0,0 +1,228 @@ +package com.alibaba.easyexcel.test.temp.fill; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.alibaba.easyexcel.test.demo.fill.FillData; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.enums.WriteDirectionEnum; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillConfig; +import com.alibaba.excel.write.metadata.fill.FillWrapper; + +import org.junit.Ignore; +import org.junit.Test; + +/** + * 写的填充写法 + * + * @since 2.1.1 + * @author Jiaju Zhuang + */ +@Ignore +public class FillTempTest { + /** + * 最简单的填充 + * + * @since 2.1.1 + */ + @Test + public void simpleFill() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + String templateFileName ="/Users/zhuangjiaju/Downloads/simple.xlsx"; + + // 方案1 根据对象填充 + String fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"; + // 这里 会填充到第一个sheet, 然后文件流会自动关闭 + FillData fillData = new FillData(); + fillData.setName("张三"); + fillData.setNumber(5.2); + EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData); + + //// 方案2 根据Map填充 + //fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"; + //// 这里 会填充到第一个sheet, 然后文件流会自动关闭 + //Map map = new HashMap(); + //map.put("name", "张三"); + //map.put("number", 5.2); + //EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map); + } + + /** + * 填充列表 + * + * @since 2.1.1 + */ + @Test + public void listFill() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // 填充list 的时候还要注意 模板中{.} 多了个点 表示list + String templateFileName = + TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "list.xlsx"; + + // 方案1 一下子全部放到内存里面 并填充 + String fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx"; + // 这里 会填充到第一个sheet, 然后文件流会自动关闭 + EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(data()); + + // 方案2 分多次 填充 会使用文件缓存(省内存) + fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + excelWriter.fill(data(), writeSheet); + excelWriter.fill(data(), writeSheet); + // 千万别忘记关闭流 + excelWriter.finish(); + } + + /** + * 复杂的填充 + * + * @since 2.1.1 + */ + @Test + public void complexFill() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // {} 代表普通变量 {.} 代表是list的变量 + String templateFileName = + TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complex.xlsx"; + + String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。 + // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用 + // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存 + // 如果数据量大 list不是最后一行 参照下一个 + FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); + excelWriter.fill(data(), fillConfig, writeSheet); + excelWriter.fill(data(), fillConfig, writeSheet); + Map map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + map.put("total", 1000); + excelWriter.fill(map, writeSheet); + excelWriter.finish(); + } + + /** + * 数据量大的复杂填充 + *

+ * 这里的解决方案是 确保模板list为最后一行,然后再拼接table.还有03版没救,只能刚正面加内存。 + * + * @since 2.1.1 + */ + @Test + public void complexFillWithTable() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // {} 代表普通变量 {.} 代表是list的变量 + // 这里模板 删除了list以后的数据,也就是统计的这一行 + String templateFileName = + TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complexFillWithTable.xlsx"; + + String fileName = TestFileUtil.getPath() + "complexFillWithTable" + System.currentTimeMillis() + ".xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + // 直接写入数据 + excelWriter.fill(data(), writeSheet); + excelWriter.fill(data(), writeSheet); + + // 写入list之前的数据 + Map map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + + // list 后面还有个统计 想办法手动写入 + // 这里偷懒直接用list 也可以用对象 + List> totalListList = new ArrayList>(); + List totalList = new ArrayList(); + totalListList.add(totalList); + totalList.add(null); + totalList.add(null); + totalList.add(null); + // 第四列 + totalList.add("统计:1000"); + // 这里是write 别和fill 搞错了 + excelWriter.write(totalListList, writeSheet); + excelWriter.finish(); + // 总体上写法比较复杂 但是也没有想到好的版本 异步的去写入excel 不支持行的删除和移动,也不支持备注这种的写入,所以也排除了可以 + // 新建一个 然后一点点复制过来的方案,最后导致list需要新增行的时候,后面的列的数据没法后移,后续会继续想想解决方案 + } + + /** + * 横向的填充 + * + * @since 2.1.1 + */ + @Test + public void horizontalFill() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // {} 代表普通变量 {.} 代表是list的变量 + String templateFileName = + TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "horizontal.xlsx"; + + String fileName = TestFileUtil.getPath() + "horizontalFill" + System.currentTimeMillis() + ".xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build(); + excelWriter.fill(data(), fillConfig, writeSheet); + excelWriter.fill(data(), fillConfig, writeSheet); + + Map map = new HashMap(); + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + + // 别忘记关闭流 + excelWriter.finish(); + } + + /** + * 多列表组合填充填充 + * + * @since 2.2.0-beta1 + */ + @Test + public void compositeFill() { + // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list + String templateFileName = + TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "composite.xlsx"; + + String fileName = TestFileUtil.getPath() + "compositeFill" + System.currentTimeMillis() + ".xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build(); + // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹 + excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet); + excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet); + excelWriter.fill(new FillWrapper("data2", data()), writeSheet); + excelWriter.fill(new FillWrapper("data2", data()), writeSheet); + excelWriter.fill(new FillWrapper("data3", data()), writeSheet); + excelWriter.fill(new FillWrapper("data3", data()), writeSheet); + + Map map = new HashMap(); + //map.put("date", "2019年10月9日13:28:28"); + map.put("date", new Date()); + + excelWriter.fill(map, writeSheet); + + // 别忘记关闭流 + excelWriter.finish(); + } + + private List data() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + FillData fillData = new FillData(); + list.add(fillData); + fillData.setName("张三"); + fillData.setNumber(5.2); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/issue1662/Data1662.java b/src/test/java/com/alibaba/easyexcel/test/temp/issue1662/Data1662.java new file mode 100644 index 00000000..53a1a5c8 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/issue1662/Data1662.java @@ -0,0 +1,20 @@ +package com.alibaba.easyexcel.test.temp.issue1662; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Data1662 { + @ExcelProperty(index = 0) + private String str; + @ExcelProperty(index = 1) + private Date date; + @ExcelProperty(index = 2) + private double r; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/issue1662/Issue1662Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/issue1662/Issue1662Test.java new file mode 100644 index 00000000..cea7e5ee --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/issue1662/Issue1662Test.java @@ -0,0 +1,44 @@ +package com.alibaba.easyexcel.test.temp.issue1662; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + +import org.junit.Ignore; +import org.junit.Test; + +@Ignore +public class Issue1662Test { + @Test + public void test1662() { + String fileName = TestFileUtil.getPath() + "Test1939" + ".xlsx"; + System.out.println(fileName); + EasyExcel.write(fileName).head(head()).sheet("模板").doWrite(dataList()); + } + + + private List> head() { + List> list = new ArrayList>(); + List head0 = new ArrayList(); + List head1 = new ArrayList(); + head0.add("xx"); + head0.add("日期"); + list.add(head0); + head1.add("日期"); + list.add(head1); + return list; + } + + private List> dataList() { + List> list = new ArrayList>(); + List data = new ArrayList(); + data.add("字符串"); + data.add(new Date()); + data.add(0.56); + list.add(data); + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/issue1663/FillData.java b/src/test/java/com/alibaba/easyexcel/test/temp/issue1663/FillData.java new file mode 100644 index 00000000..57b54107 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/issue1663/FillData.java @@ -0,0 +1,9 @@ +package com.alibaba.easyexcel.test.temp.issue1663; + +import lombok.Data; + +@Data +public class FillData { + private String name; + private double number; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/issue1663/FillTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/issue1663/FillTest.java new file mode 100644 index 00000000..7f89621c --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/issue1663/FillTest.java @@ -0,0 +1,50 @@ +package com.alibaba.easyexcel.test.temp.issue1663; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.alibaba.easyexcel.test.demo.fill.FillData; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.enums.WriteDirectionEnum; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillConfig; +import com.alibaba.excel.write.metadata.fill.FillWrapper; + +import org.junit.Ignore; +import org.junit.Test; + +@Ignore +public class FillTest { + @Test + public void TestFillNullPoint(){ + String templateFileName = + TestFileUtil.getPath() + "temp/issue1663" + File.separator + "template.xlsx"; + + String fileName = TestFileUtil.getPath() + "temp/issue1663" + File.separator + "issue1663.xlsx"; + ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.VERTICAL).build(); + excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet); + + Map map = new HashMap(); + // Variable {date} does not exist in the template.xlsx, which should be ignored instead of reporting an error. + map.put("date", "2019年10月9日13:28:28"); + excelWriter.fill(map, writeSheet); + excelWriter.finish(); + } + private List data() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + com.alibaba.easyexcel.test.demo.fill.FillData fillData = new FillData(); + list.add(fillData); + fillData.setName("张三"); + fillData.setNumber(5.2); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/large/TempLargeDataTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/large/TempLargeDataTest.java index 0bde12ef..7f4a6717 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/large/TempLargeDataTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/large/TempLargeDataTest.java @@ -1,16 +1,19 @@ package com.alibaba.easyexcel.test.temp.large; +import java.io.File; import java.io.FileInputStream; +import java.lang.reflect.Field; +import com.alibaba.easyexcel.test.core.large.LargeDataTest; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + +import org.apache.poi.openxml4j.util.ZipSecureFile; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.easyexcel.test.core.large.LargeDataTest; -import com.alibaba.easyexcel.test.util.TestFileUtil; -import com.alibaba.excel.EasyExcel; - /** * @author Jiaju Zhuang */ @@ -29,9 +32,24 @@ public class TempLargeDataTest { @Test public void noModelRead() throws Exception { + ZipSecureFile.setMaxEntrySize(Long.MAX_VALUE); long start = System.currentTimeMillis(); EasyExcel.read(TestFileUtil.readUserHomeFile("test/ld.xlsx"), new NoModelLargeDataListener()) .sheet().doRead(); LOGGER.info("Large data total time spent:{}", System.currentTimeMillis() - start); } + + @Test + public void noModelRead2() throws Exception { + Field field = ZipSecureFile.class.getDeclaredField("MAX_ENTRY_SIZE"); + field.setAccessible(true); + field.set(null, Long.MAX_VALUE); + + long start = System.currentTimeMillis(); + EasyExcel.read( + new File("/Users/zhuangjiaju/IdeaProjects/easyexcel/target/test-classes/large1617887262709.xlsx"), + new NoModelLargeDataListener()) + .sheet().doRead(); + LOGGER.info("Large data total time spent:{}", System.currentTimeMillis() - start); + } } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiEncryptTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiEncryptTest.java new file mode 100644 index 00000000..67b6cfc7 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiEncryptTest.java @@ -0,0 +1,79 @@ +package com.alibaba.easyexcel.test.temp.poi; + +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.easyexcel.test.core.encrypt.EncryptData; +import com.alibaba.easyexcel.test.core.simple.SimpleData; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionMode; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Ignore; +import org.junit.Test; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +@Ignore +public class PoiEncryptTest { + @Test + public void encrypt() throws Exception { + + + + XSSFWorkbook workbook = new XSSFWorkbook(); + SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook); + + Sheet sheet = sxssfWorkbook.createSheet("sheet1"); + sheet.createRow(0).createCell(0).setCellValue("T2"); + + + POIFSFileSystem fs = new POIFSFileSystem(); + EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile); + + Encryptor enc = info.getEncryptor(); + enc.confirmPassword("123456"); + + // write the workbook into the encrypted OutputStream + OutputStream encos = enc.getDataStream(fs); + sxssfWorkbook.write(encos); + sxssfWorkbook.dispose(); + sxssfWorkbook.close(); + encos.close(); // this is necessary before writing out the FileSystem + + OutputStream os = new FileOutputStream( + TestFileUtil.createNewFile("encrypt" + System.currentTimeMillis() + ".xlsx")); + fs.writeFilesystem(os); + os.close(); + fs.close(); + } + + @Test + public void encryptExcel() throws Exception { + EasyExcel.write(TestFileUtil.createNewFile("encryptv2" + System.currentTimeMillis() + ".xlsx"), + EncryptData.class).password("123456") + .sheet().doWrite(data()); + } + + private List data() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + SimpleData simpleData = new SimpleData(); + simpleData.setName("姓名" + i); + list.add(simpleData); + } + return list; + } + +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java index f7778338..d56bd7b8 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java @@ -3,11 +3,13 @@ package com.alibaba.easyexcel.test.temp.poi; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Date; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.util.FileUtils; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellCopyPolicy; -import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.streaming.SXSSFRow; @@ -21,11 +23,6 @@ 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.util.FileUtils; - /** * 测试poi * @@ -37,27 +34,30 @@ public class PoiTest { @Test public void lastRowNum() throws IOException { - String file = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; + String file = "/Users/zhuangjiaju/test/test3.xlsx"; SXSSFWorkbook xssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(file)); SXSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0); LOGGER.info("一共行数:{}", xssfSheet.getLastRowNum()); SXSSFRow row = xssfSheet.getRow(0); - LOGGER.info("第一行数据:{}", row); - xssfSheet.createRow(20); - LOGGER.info("一共行数:{}", xssfSheet.getLastRowNum()); + LOGGER.info("dd{}",row.getCell(0).getColumnIndex()); + Date date = row.getCell(1).getDateCellValue(); + + } @Test public void lastRowNumXSSF() throws IOException { - String file = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; + String file = "/Users/zhuangjiaju/test/test3.xlsx"; XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file); LOGGER.info("一共:{}个sheet", xssfWorkbook.getNumberOfSheets()); XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0); LOGGER.info("一共行数:{}", xssfSheet.getLastRowNum()); XSSFRow row = xssfSheet.getRow(0); - LOGGER.info("第一行数据:{}", row); - xssfSheet.createRow(20); - LOGGER.info("一共行数:{}", xssfSheet.getLastRowNum()); + LOGGER.info("dd{}",row.getCell(0).getRow().getRowNum()); + LOGGER.info("dd{}",xssfSheet.getLastRowNum()); + + Date date = row.getCell(1).getDateCellValue(); + LOGGER.info("date{}",date); } @Test diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/TestCell.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/TestCell.java index 3c4e0ab6..0edc995d 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/poi/TestCell.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/TestCell.java @@ -2,7 +2,7 @@ package com.alibaba.easyexcel.test.temp.poi; import java.util.List; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.CellData; import lombok.Data; @@ -13,6 +13,6 @@ import lombok.Data; **/ @Data public class TestCell { - private CellData c1; + private CellData c1; private CellData> c2; } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java index 22de3956..48512b6c 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java @@ -10,7 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.data.CellData; import com.alibaba.fastjson.JSON; /** diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java index e52dc51a..1c58e798 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HDListener.java @@ -7,7 +7,6 @@ import org.slf4j.LoggerFactory; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; -import com.alibaba.excel.metadata.CellData; import com.alibaba.fastjson.JSON; /** diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java index 40aa4b8f..6649c2fe 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java @@ -1,19 +1,16 @@ package com.alibaba.easyexcel.test.temp.read; import java.io.File; -import java.io.FileInputStream; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.cache.Ehcache; 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.cache.Ehcache; -import com.alibaba.excel.support.ExcelTypeEnum; - /** * 临时测试 * @@ -22,13 +19,6 @@ import com.alibaba.excel.support.ExcelTypeEnum; @Ignore public class HeadReadTest { private static final Logger LOGGER = LoggerFactory.getLogger(HeadReadTest.class); - @Test - public void testread() throws Exception { - FileInputStream fileInputStream = new FileInputStream("D://test/t1.xlsx"); - - ExcelReader excelReader = new ExcelReader(fileInputStream, ExcelTypeEnum.XLSX, null, new TestListener()); - excelReader.read(); - } @Test public void test() throws Exception { @@ -48,4 +38,5 @@ public class HeadReadTest { EasyExcel.read(file, HeadReadData.class, new HDListener()).readCache(new Ehcache(20)).sheet(0).doRead(); } + } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java index ffabd105..3cc54749 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java @@ -5,21 +5,21 @@ import java.util.Date; 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.core.large.LargeData; import com.alibaba.easyexcel.test.demo.write.DemoData; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.util.BeanMapUtils; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.fastjson.JSON; -import net.sf.cglib.beans.BeanMap; +import lombok.extern.slf4j.Slf4j; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * 测试poi @@ -27,6 +27,7 @@ import net.sf.cglib.beans.BeanMap; * @author Jiaju Zhuang **/ @Ignore +@Slf4j public class Wirte { private static final Logger LOGGER = LoggerFactory.getLogger(Wirte.class); @@ -34,7 +35,7 @@ public class Wirte { public void simpleWrite1() { LargeData ss = new LargeData(); ss.setStr23("ttt"); - Map map = BeanMap.create(ss); + Map map = BeanMapUtils.create(ss); System.out.println(map.containsKey("str23")); System.out.println(map.containsKey("str22")); System.out.println(map.get("str23")); @@ -43,6 +44,7 @@ public class Wirte { @Test public void simpleWrite() { + log.info("t5"); // 写法1 String fileName = TestFileUtil.getPath() + "t22" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 @@ -56,7 +58,18 @@ public class Wirte { String fileName = TestFileUtil.getPath() + "t22" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 - EasyExcel.write(fileName, WriteData.class).sheet("模板").registerWriteHandler(new WriteHandler()).doWrite(data1()); + EasyExcel.write(fileName, WriteData.class).sheet("模板").registerWriteHandler(new WriteHandler()).doWrite( + data1()); + } + + @Test + public void simpleWrite3() { + // 写法1 + String fileName = TestFileUtil.getPath() + "t33" + System.currentTimeMillis() + ".xlsx"; + // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 + // 如果这里想使用03 则 传入excelType参数即可 + EasyExcel.write(fileName).head(head()).inMemory(true).sheet("模板").registerWriteHandler(new WriteCellHandler()).doWrite( + data1()); } @Test @@ -125,7 +138,7 @@ public class Wirte { List list = new ArrayList(); for (int i = 0; i < 10; i++) { WriteData data = new WriteData(); - data.setF(300.35f); + data.setDd(new Date()); data.setF1(33f); list.add(data); } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteCellHandler.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteCellHandler.java new file mode 100644 index 00000000..b92005c7 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteCellHandler.java @@ -0,0 +1,39 @@ +package com.alibaba.easyexcel.test.temp.simple; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; + +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.DataFormat; +import org.apache.poi.ss.usermodel.IndexedColors; + +/** + * @author Jiaju Zhuang + */ +@Slf4j +public class WriteCellHandler implements CellWriteHandler { + + @Override + public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + WriteCellData cellData, Cell cell, Head head, Integer integer, Boolean isHead) { + + if (!isHead) { + CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper(); + CellStyle cellStyle = writeSheetHolder.getSheet().getWorkbook().createCellStyle(); + if (cellStyle != null) { + DataFormat dataFormat = createHelper.createDataFormat(); + cellStyle.setWrapText(true); + cellStyle.setFillBackgroundColor(IndexedColors.RED.getIndex()); + cellStyle.setBottomBorderColor(IndexedColors.RED.getIndex()); + cellStyle.setDataFormat(dataFormat.getFormat("yyyy-MM-dd")); + cell.setCellStyle(cellStyle); + } + } + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java index 2b25bb0a..27967b9f 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java @@ -1,5 +1,7 @@ package com.alibaba.easyexcel.test.temp.simple; +import java.util.Date; + import com.alibaba.excel.annotation.write.style.ContentStyle; import lombok.Data; @@ -12,7 +14,7 @@ import lombok.Data; @Data public class WriteData { // @ContentStyle(locked = true) - private float f; + private Date dd; // @ContentStyle(locked = false) private float f1; } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java index 1420b2b0..a82543eb 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java @@ -1,6 +1,7 @@ package com.alibaba.easyexcel.test.temp.simple; import com.alibaba.excel.write.handler.AbstractSheetWriteHandler; +import com.alibaba.excel.write.handler.SheetWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; @@ -10,7 +11,7 @@ import lombok.extern.slf4j.Slf4j; * @author Jiaju Zhuang */ @Slf4j -public class WriteHandler extends AbstractSheetWriteHandler { +public class WriteHandler implements SheetWriteHandler { @Override public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, diff --git a/src/test/resources/converter/converter03.xls b/src/test/resources/converter/converter03.xls index 3373d81e..89c2ab6e 100644 Binary files a/src/test/resources/converter/converter03.xls and b/src/test/resources/converter/converter03.xls differ diff --git a/src/test/resources/converter/converter07.xlsx b/src/test/resources/converter/converter07.xlsx index 92b93e20..99ace690 100644 Binary files a/src/test/resources/converter/converter07.xlsx and b/src/test/resources/converter/converter07.xlsx differ diff --git a/src/test/resources/converter/converterCsv.csv b/src/test/resources/converter/converterCsv.csv new file mode 100644 index 00000000..01bcf2ef --- /dev/null +++ b/src/test/resources/converter/converterCsv.csv @@ -0,0 +1,2 @@ +大数的布尔(不支持),大数的数字,大数的字符串,大整数的布尔(不支持),大整数的数字,大整数的字符串,布尔的布尔,布尔的数字(不支持),布尔的字符串,字节的布尔(不支持),字节的数字,字节的字符串,日期的数字,日期的字符串,本地日期的数字,本地日期的字符串,双精度浮点的布尔(不支持),双精度浮点的数字,双精度浮点的字符串,浮点的布尔(不支持),浮点的数字,浮点的字符串,整型的布尔(不支持),整型的数字,整型的字符串,长整型的布尔(不支持),长整型的数字,长整型的字符串,短整型的布尔(不支持),短整型的数字,短整型的字符串,字符串的布尔,字符串的数字,字符串的字符串,字符串的错误,字符串的数字公式,字符串的字符串公式,字符串的数字日期 +1,1,1,1,1,1,TRUE,TRUE,TRUE,1,1,1,2020-01-01 01:01:01,2020-01-01 01:01:01,2020-01-01 01:01:01,2020-01-01 01:01:01,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,TRUE,1,测试,#VALUE!,2,1测试,2020-01-01 01:01:01 \ No newline at end of file diff --git a/src/test/resources/temp/issue1663/template.xlsx b/src/test/resources/temp/issue1663/template.xlsx new file mode 100644 index 00000000..a968ff41 Binary files /dev/null and b/src/test/resources/temp/issue1663/template.xlsx differ diff --git a/update.md b/update.md index c90c4aea..4ced0a04 100644 --- a/update.md +++ b/update.md @@ -1,26 +1,67 @@ +# 3.0.0-beta1 + +* 升级jdk8 不再支持jdk6 jdk7 +* 升级poi 到 4.1.2 +* 升级cglib 到 3.3.0 +* 升级ehcache 到 3.8.1 +* 支持非驼峰的字段读写 +* 支持csv的读&写 +* 修复`CellData`可能不返回行列号 [Issue #1832](https://github.com/alibaba/easyexcel/issues/1832) +* 优化读取性能 +* 修复部分情况下不抛出异常 +* 07版在导出的时候会导出 行数 [Issue #1282](https://github.com/alibaba/easyexcel/issues/1282) +* 修复没有样式的情况下空指针异常 [Issue #1738](https://github.com/alibaba/easyexcel/issues/1738) +* 修改异常抛出逻辑 [Issue #1618](https://github.com/alibaba/easyexcel/issues/1618) +* 兼容一些非官方excel的情况 [Issue #1527](https://github.com/alibaba/easyexcel/issues/1527) +* 修改读的关闭流无效 [Issue #1840](https://github.com/alibaba/easyexcel/issues/1840) +* 写入支持Collection [Issue #1834](https://github.com/alibaba/easyexcel/issues/1834) +* `Converter`支持null转换 [Issue #1776](https://github.com/alibaba/easyexcel/issues/1776) +* cglib 新增命名策略,防止和`spring`的冲突 [Issue #2064](https://github.com/alibaba/easyexcel/issues/2064) +* 修改填充可能填充错误的bug [Issue #2035](https://github.com/alibaba/easyexcel/issues/2035) +* 修复无对象读 返回map的size可能会头的size不一致 [Issue #2014](https://github.com/alibaba/easyexcel/issues/2014) +* 修复合并头可能异常的bug [Issue #1662](https://github.com/alibaba/easyexcel/issues/1662) +* 修复填充调用横向样式策略报错 [Issue #1651](https://github.com/alibaba/easyexcel/issues/1651) +* 修复不自动行高的问题 [Issue #1869](https://github.com/alibaba/easyexcel/issues/1869) +* 新增头的非空校验 [Issue #1765](https://github.com/alibaba/easyexcel/issues/1765) +* 修复某些特殊的excel读取失败的问题 [Issue #1595](https://github.com/alibaba/easyexcel/issues/1595) +* 修复不创建对象写入数据异常 [Issue #1702](https://github.com/alibaba/easyexcel/issues/1702) +* 修复头和数据对象不一致会覆盖的问题 [Issue #1870](https://github.com/alibaba/easyexcel/issues/1870) +* 修复忽略字段后可能排序不一致的问题 +* 修改填充时,无法使用生成的模板 [Issue #1552](https://github.com/alibaba/easyexcel/issues/1552) +* 修改填充可以不自动继承样式 [Issue #1710](https://github.com/alibaba/easyexcel/issues/1710) +* 修复填充数据不能为空的问题 [Issue #1703](https://github.com/alibaba/easyexcel/issues/1703) +* 新增部分jdk8特性 + # 2.2.11 * 修复有些xlsx解析失败的bug [Issue #1595](https://github.com/alibaba/easyexcel/issues/1595) # 2.2.10 + * 修复读取的时候用string接收数字 可能四舍五入不一致的bug # 2.2.9 + * 修复读取的时候用string接收数字 可能四舍五入不一致的bug # 2.2.8 + * 兼容07在特殊的excel的情况下,读取数据异常 # 2.2.7 + * 修改07在特殊情况下用`String`接收数字会丢小数位的bug # 2.2.6 + * 修改跳着读取03版本空指针bug # 2.2.5 + * `ExcelProperty`新增`order` 用于排序 -* 修复导出指定`index`会导致空行的bug +* 修复导出指定`index`会导致空行的bug # 2.2.4 + * 撤销删除`AbstractMergeStrategy` * 修改默认用String读取数字不使用科学计数法 通过`useScientificFormat`修改 * 修复07版仅有样式的空行 默认不忽略的bug @@ -34,14 +75,17 @@ * 修复`@NumberFormat`注解转换double时可能会丢失精度 [Issue #1306](https://github.com/alibaba/easyexcel/issues/1306) # 2.2.3 + * 修改填充数据空数据的bug [Issue #1274](https://github.com/alibaba/easyexcel/issues/1274) * 回退自定义转换器入参为空 # 2.2.2 + * 修改`sheet`事件未调用的bug * 修复复杂表头不是`index=0`开始 合并异常的bug [Issue #1322](https://github.com/alibaba/easyexcel/issues/1322) # 2.2.1 + * 发布正式版 * 修复第一行为空不会调用`invokeHeadMap`的bug [Issue #993](https://github.com/alibaba/easyexcel/issues/993) * 当类的属性没有按照ExcelProperty的属性index顺序排序的时候,写数据出现错乱 [Issue #1046](https://github.com/alibaba/easyexcel/issues/1046) @@ -51,11 +95,13 @@ * 修复`table`、`sheet`中创建的拦截器不执行`workbook`事件的bug [Issue #1202](https://github.com/alibaba/easyexcel/issues/1202) # 2.2.0-beta2 + * 修复最长匹配策略不同表格会有影响的bug [Issue #1010](https://github.com/alibaba/easyexcel/issues/1010) * `LinkedList`写入的性能问题 #1121 * 修复在某些情况下可能出现不必要的`warn`日志 # 2.2.0-beta1 + * 重写主流程,代码更加优雅 * 修复用String接收日期、数字和excel显示不一致的bug(不是完美修复,但是大部分情况已经兼容) * 降低Ehcache版本 3.7.1(jkd7) -> 3.4.0(jdk6) @@ -73,19 +119,24 @@ * 填充支持多个List对象 # 2.1.7 + * 修复使用1+版本的写法,第1条开始读修改为第0条开始读 # 2.1.6 + * 修复写入只有`sheetName`会抛异常 # 2.1.5 + * 修复部分xlsx没有行号读取异常 * 填充时候支持根据`sheetName`定位`sheet` # 2.1.4 + * 新增参数`useDefaultListener` 可以排除默认对象转换 # 2.1.3 + * 每个java进程单独创建一个缓存目录 [Issue #813](https://github.com/alibaba/easyexcel/issues/813) * 统一修改合并为unsafe,提高大量数据导出的合并的效率 * 修改merge返回参数`relativeRowIndex`为`Integer` @@ -95,9 +146,11 @@ * `SimpleColumnWidthStyleStrategy` 新增 参数`columnIndex` [Issue #806](https://github.com/alibaba/easyexcel/issues/806) # 2.1.2 + * 修复强制创建新行填充,只有一行数据会未填充的bug # 2.1.1 + * 发布正式版 * 修改map返回为LinkedHashMap * 修改同步读取返回对象支持泛型 @@ -113,11 +166,13 @@ * 修复03版无法获取大概总行数的bug # 2.1.0-beta4 + * 修改最长匹配策略会空指针的bug [Issue #747](https://github.com/alibaba/easyexcel/issues/747) * 修改afterRowDispose错误 [Issue #751](https://github.com/alibaba/easyexcel/issues/751) * 修复多个头的情况下会读取数据为空 # 2.1.0-beta3 + * 支持强行指定在内存处理,以支持备注、RichTextString等的写入 * 修复关闭流失败,可能会不删除临时文件的问题 * 支持根据参数自定义导出列 @@ -126,11 +181,13 @@ * 修复填充的时候有数字会异常 # 2.1.0-beta2 + * 修改模板通过流创建报错的bug * 修复空数据未替换掉的bug * 修复空模板会空一行的bug # 2.1.0-beta1 + * 新增支持导入、导出支持公式 * 新增支持读取单元格类型、写入指定单元格类型 * 支持通过模板填充数据 @@ -143,53 +200,65 @@ * 支持导入加密 [Issue #295](https://github.com/alibaba/easyexcel/issues/295) # 2.0.5 + * 优化07版超大文件读取方案 * 支持自己设置超大文件读取参数 * 读取xlsx会改变修改时间的bug [Issue #574](https://github.com/alibaba/easyexcel/issues/574) * 默认读取忽略空行 根据参数ignoreEmptyRow参数设置 # 2.0.4 + * 修复07版整个excel仅存在数字时会出现的NPE * 修复03版 用String接收电话会出现科学计数法的问题 # 2.0.3 + * 修复重大bug 在07版读取文件的时候 小概率导致数字部分丢失 # 2.0.2 + * 修复xls无法获取sheetList的bug [Issue #621](https://github.com/alibaba/easyexcel/issues/621) * 修复监听器转换异常会重复提示的bug # 2.0.1 + * 降级poi为3.17 兼容jdk6 # 2.0.0 + * 修复当cell为空可能会抛出空指针的bug * 修复电话等长数字可能出现科学计数法的问题 [Issue #583](https://github.com/alibaba/easyexcel/issues/583) * 升级为正式版 # 2.0.0-beta6 + * 修复空行读取空指针异常 * 修复写入指定头为List>,但是数据用List导致的空指针 # 2.0.0-beta5 + * 修复在读取值的时候读取了额外值导致数据转换异常 # 2.0.0-beta4 + * 修改在传入List>判断行数错误 [Issue #526](https://github.com/alibaba/easyexcel/issues/526) * 修复在mac 2016 2017导出的excel 可能存在多余字段的问题 * 修复03版 读取无法指定sheet的问题 [Issue #533](https://github.com/alibaba/easyexcel/issues/533) # 2.0.0-beta3 + * 导出完成移除临时目录 [Issue #386](https://github.com/alibaba/easyexcel/issues/386) * 新增读取返回头数据 # 2.0.0-beta2 + * 加速gc回收 [Issue #511](https://github.com/alibaba/easyexcel/issues/511) * 修改空字符串读取可能读取上个字段的数据的bug * 修改换行数据无法读取的bug [Issue #521](https://github.com/alibaba/easyexcel/issues/521) * 修复在空字符串的时候 格式转换异常 [Issue #520](https://github.com/alibaba/easyexcel/issues/520) # 2.0.0-beta1 + * 优化读写逻辑 * 优化读写对外接口 * 加入转换器,方便格式转换 @@ -199,31 +268,41 @@ * 升级poi 到4.0.1 # 1.2.4 + 修复read()方法存在的bug # 1.2.1 + 修复POI在大并发情况下创建临时目录失败的bug -# 1.0.9 +# 1.0.9 + 修复excel超过16列被覆盖的问题,修复数据只有一行时候无法透传的bug。 # 1.0.8 + 如果整行excel数据全部为空,则不解析返回。完善多sheet的解析。 # 1.0.6 + 增加@ExcelColumnNum,修复字符串前后空白,增加过滤功能。 # 1.0.5 + 优化类型转换的性能。 # 1.0.4 + 修复日期类型转换时候数字问题。基础模型支持字段类型int,long,double,boolean,date,string # 1.0.3 + 修复无@ExcelProperty标注的多余字段时候报错。 -# 1.0.2 +# 1.0.2 + 修复拿到一行数据后,存到list中,但最后处理时候变为空的bug。 # 1.0.1 + 完善测试用例,防止歧义,模型字段映射不上时候有抛异常,改为提醒。 \ No newline at end of file