Browse Source

Merge pull request #524 from alibaba/2.0.0-beta3

2.0.0 beta3
bugfix v2.0.0-beta3
Jiaju Zhuang 5 years ago committed by GitHub
parent
commit
9dbd586906
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      pom.xml
  2. 91
      quickstart.md
  3. 25
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
  4. 30
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  5. 17
      src/main/java/com/alibaba/excel/event/AnalysisEventListener.java
  6. 37
      src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java
  7. 13
      src/main/java/com/alibaba/excel/read/listener/ReadListener.java
  8. 57
      src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java
  9. 87
      src/main/java/com/alibaba/excel/util/ConverterUtils.java
  10. 4
      src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java
  11. 4
      src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationIndexAndNameDataTest.java
  12. 4
      src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataTest.java
  13. 2
      src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityParameterDataTest.java
  14. 12
      src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataTest.java
  15. 4
      src/test/java/com/alibaba/easyexcel/test/core/exception/ExceptionDataTest.java
  16. 4
      src/test/java/com/alibaba/easyexcel/test/core/head/ComplexHeadDataTest.java
  17. 4
      src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataTest.java
  18. 4
      src/test/java/com/alibaba/easyexcel/test/core/head/NoHeadDataTest.java
  19. 2
      src/test/java/com/alibaba/easyexcel/test/core/parameter/ParameterDataTest.java
  20. 8
      src/test/java/com/alibaba/easyexcel/test/core/repetition/RepetitionDataTest.java
  21. 7
      src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataListener.java
  22. 10
      src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataTest.java
  23. 8
      src/test/java/com/alibaba/easyexcel/test/core/style/StyleDataTest.java
  24. 4
      src/test/java/com/alibaba/easyexcel/test/core/template/TemplateDataTest.java
  25. 73
      src/test/java/com/alibaba/easyexcel/test/demo/read/DemoHeadDataListener.java
  26. 34
      src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java
  27. 4
      update.md

2
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId> <artifactId>easyexcel</artifactId>
<version>2.0.0-beta2</version> <version>2.0.0-beta3</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>easyexcel</name> <name>easyexcel</name>

91
quickstart.md

@ -7,6 +7,12 @@
* 单个文件的并发写入、读取 * 单个文件的并发写入、读取
* 读取图片 * 读取图片
* 宏 * 宏
#### 关于常见类解析
* EasyExcel 入口类,用于构建开始各种操作
* ExcelReaderBuilder ExcelWriterBuilder 构建出一个 ReadWorkbook WriteWorkbook,可以理解成一个excel对象,一个excel只要构建一个
* ExcelReaderSheetBuilder ExcelWriterSheetBuilder 构建出一个 ReadSheet WriteSheet对象,可以理解成excel里面的一页,每一页都要构建一个
* ReadListener 在每一行读取完毕后都会调用ReadListener来处理数据
* WriteHandler 在每一个操作包括创建单元格、创建表格等都会调用WriteHandler来处理数据
#### 开源项目不容易,如果觉得本项目对您的工作还是有帮助的话,请在右上角帮忙点个★Star。 #### 开源项目不容易,如果觉得本项目对您的工作还是有帮助的话,请在右上角帮忙点个★Star。
### 读 ### 读
DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/demo/read/ReadTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java) DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/demo/read/ReadTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java)
@ -16,7 +22,10 @@ DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/ja
* [日期、数字或者自定义格式转换](#converterRead) * [日期、数字或者自定义格式转换](#converterRead)
* [多行头](#complexHeaderRead) * [多行头](#complexHeaderRead)
* [同步的返回](#synchronousRead) * [同步的返回](#synchronousRead)
* [读取表头数据](#headerRead)
* [数据转换等异常处理](#exceptionRead)
* [web中的读](#webRead) * [web中的读](#webRead)
### 写 ### 写
DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java) DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java)
* [最简单的写](#simpleWrite) * [最简单的写](#simpleWrite)
@ -331,6 +340,88 @@ public class CustomStringStringConverter implements Converter<String> {
} }
``` ```
### <span id="headerRead" />读取表头数据
##### excel示例
参照:[excel示例](#simpleReadExcel)
##### 对象
参照:[对象](#simpleReadObject)
##### 监听器
参照:[监听器](#simpleReadListener)
里面多了一个方法,只要重写invokeHeadMap方法即可
```java
/**
* 这里会一行行的返回头
*
* @param headMap
* @param context
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
}
```
##### 代码
```java
/**
* 读取表头数据
*
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData}
* <p>
* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoHeadDataListener}
* <p>
* 3. 直接读即可
*/
@Test
public void headerRead() {
String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 然后千万别忘记 finish
EasyExcel.read(fileName, DemoData.class, new DemoHeadDataListener()).sheet().doRead();
}
```
### <span id="exceptionRead" />数据转换等异常处理
##### excel示例
参照:[excel示例](#simpleReadExcel)
##### 对象
参照:[对象](#simpleReadObject)
##### 监听器
参照:[监听器](#simpleReadListener)
里面多了一个方法,只要重写onException方法即可
```java
/**
* 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
*
* @param exception
* @param context
* @throws Exception
*/
@Override
public void onException(Exception exception, AnalysisContext context) {
LOGGER.error("解析失败,但是继续解析下一行", exception);
}
```
##### 代码
```java
/**
* 数据转换等异常处理
*
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData}
* <p>
* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoHeadDataListener}
* <p>
* 3. 直接读即可
*/
@Test
public void exceptionRead() {
String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 然后千万别忘记 finish
EasyExcel.read(fileName, DemoData.class, new DemoHeadDataListener()).sheet().doRead();
}
```
### <span id="webRead" />web中的读 ### <span id="webRead" />web中的读
##### 示例代码 ##### 示例代码
DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java) DEMO代码地址:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java](/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java)

25
src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java

@ -15,6 +15,7 @@ import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.context.AnalysisContextImpl; import com.alibaba.excel.context.AnalysisContextImpl;
import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelAnalysisStopException; import com.alibaba.excel.exception.ExcelAnalysisStopException;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.read.metadata.ReadWorkbook;
import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder;
@ -113,38 +114,42 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
if (readWorkbookHolder.getReadCache() != null) { if (readWorkbookHolder.getReadCache() != null) {
readWorkbookHolder.getReadCache().destroy(); readWorkbookHolder.getReadCache().destroy();
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelAnalysisException("Can not close IO", e); throwCanNotCloseIo(t);
} }
try { try {
if (readWorkbookHolder.getOpcPackage() != null) { if (readWorkbookHolder.getOpcPackage() != null) {
readWorkbookHolder.getOpcPackage().close(); readWorkbookHolder.getOpcPackage().close();
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelAnalysisException("Can not close IO", e); throwCanNotCloseIo(t);
} }
try { try {
if (readWorkbookHolder.getPoifsFileSystem() != null) { if (readWorkbookHolder.getPoifsFileSystem() != null) {
readWorkbookHolder.getPoifsFileSystem().close(); readWorkbookHolder.getPoifsFileSystem().close();
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelAnalysisException("Can not close IO", e); throwCanNotCloseIo(t);
} }
try { try {
if (analysisContext.readWorkbookHolder().getAutoCloseStream() if (analysisContext.readWorkbookHolder().getAutoCloseStream()
&& readWorkbookHolder.getInputStream() != null) { && readWorkbookHolder.getInputStream() != null) {
readWorkbookHolder.getInputStream().close(); readWorkbookHolder.getInputStream().close();
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelAnalysisException("Can not close IO", e); throwCanNotCloseIo(t);
} }
try { try {
if (readWorkbookHolder.getTempFile() != null) { if (readWorkbookHolder.getTempFile() != null) {
FileUtils.delete(readWorkbookHolder.getTempFile()); FileUtils.delete(readWorkbookHolder.getTempFile());
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelAnalysisException("Can not close IO", e); throwCanNotCloseIo(t);
}
} }
private void throwCanNotCloseIo(Throwable t) {
throw new ExcelAnalysisException("Can not close IO", t);
} }
@Override @Override

30
src/main/java/com/alibaba/excel/context/WriteContextImpl.java

@ -9,6 +9,7 @@ import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -343,39 +344,52 @@ public class WriteContextImpl implements WriteContext {
if (writeWorkbookHolder == null) { if (writeWorkbookHolder == null) {
return; return;
} }
try { try {
writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream()); writeWorkbookHolder.getWorkbook().write(writeWorkbookHolder.getOutputStream());
writeWorkbookHolder.getWorkbook().close(); writeWorkbookHolder.getWorkbook().close();
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelGenerateException("Can not close IO", e); throwCanNotCloseIo(t);
}
try {
Workbook workbook = writeWorkbookHolder.getWorkbook();
if (workbook instanceof SXSSFWorkbook) {
((SXSSFWorkbook)workbook).dispose();
}
} catch (Throwable t) {
throwCanNotCloseIo(t);
} }
try { try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) { if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close(); writeWorkbookHolder.getOutputStream().close();
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelGenerateException("Can not close IO", e); throwCanNotCloseIo(t);
} }
try { try {
if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getTemplateInputStream() != null) { if (writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getTemplateInputStream() != null) {
writeWorkbookHolder.getTemplateInputStream().close(); writeWorkbookHolder.getTemplateInputStream().close();
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelGenerateException("Can not close IO", e); throwCanNotCloseIo(t);
} }
try { try {
if (!writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getFile() != null if (!writeWorkbookHolder.getAutoCloseStream() && writeWorkbookHolder.getFile() != null
&& writeWorkbookHolder.getOutputStream() != null) { && writeWorkbookHolder.getOutputStream() != null) {
writeWorkbookHolder.getOutputStream().close(); writeWorkbookHolder.getOutputStream().close();
} }
} catch (Throwable e) { } catch (Throwable t) {
throw new ExcelGenerateException("Can not close IO", e); throwCanNotCloseIo(t);
} }
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Finished write."); LOGGER.debug("Finished write.");
} }
} }
private void throwCanNotCloseIo(Throwable t) {
throw new ExcelGenerateException("Can not close IO", t);
}
@Override @Override
public Sheet getCurrentSheet() { public Sheet getCurrentSheet() {
return writeSheetHolder.getSheet(); return writeSheetHolder.getSheet();

17
src/main/java/com/alibaba/excel/event/AnalysisEventListener.java

@ -1,7 +1,11 @@
package com.alibaba.excel.event; package com.alibaba.excel.event;
import java.util.Map;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ConverterUtils;
/** /**
* Receives the return of each piece of data parsed * Receives the return of each piece of data parsed
@ -10,6 +14,19 @@ import com.alibaba.excel.read.listener.ReadListener;
*/ */
public abstract class AnalysisEventListener<T> implements ReadListener<T> { public abstract class AnalysisEventListener<T> implements ReadListener<T> {
@Override
public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context.currentReadHolder()), context);
}
/**
* Returns the header as a map.Override the current method to receive header data.
*
* @param headMap
* @param context
*/
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {}
/** /**
* All listeners receive this method when any one Listener does an error report. If an exception is thrown here, the * All listeners receive this method when any one Listener does an error report. If an exception is thrown here, the
* entire read will terminate. * entire read will terminate.

37
src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java

@ -18,6 +18,7 @@ import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.read.metadata.holder.ReadHolder; import com.alibaba.excel.read.metadata.holder.ReadHolder;
import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty;
import com.alibaba.excel.util.ConverterUtils;
import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.BeanMap;
@ -28,6 +29,9 @@ import net.sf.cglib.beans.BeanMap;
*/ */
public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener<Map<Integer, CellData>> { public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener<Map<Integer, CellData>> {
@Override
public void invokeHead(Map<Integer, CellData> cellDataMap, AnalysisContext context) {}
@Override @Override
public void invoke(Map<Integer, CellData> cellDataMap, AnalysisContext context) { public void invoke(Map<Integer, CellData> cellDataMap, AnalysisContext context) {
ReadHolder currentReadHolder = context.currentReadHolder(); ReadHolder currentReadHolder = context.currentReadHolder();
@ -48,7 +52,7 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
map.put(entry.getKey(), null); map.put(entry.getKey(), null);
continue; continue;
} }
map.put(entry.getKey(), (String)convertValue(cellData, String.class, null, map.put(entry.getKey(), (String)ConverterUtils.convertToJavaObject(cellData, String.class, null,
currentReadHolder.converterMap(), currentReadHolder.globalConfiguration())); currentReadHolder.converterMap(), currentReadHolder.globalConfiguration()));
} }
return map; return map;
@ -61,8 +65,8 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
list.add(null); list.add(null);
continue; continue;
} }
list.add((String)convertValue(cellData, String.class, null, currentReadHolder.converterMap(), list.add((String)ConverterUtils.convertToJavaObject(cellData, String.class, null,
currentReadHolder.globalConfiguration())); currentReadHolder.converterMap(), currentReadHolder.globalConfiguration()));
} }
return list; return list;
} }
@ -90,8 +94,8 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
continue; continue;
} }
ExcelContentProperty excelContentProperty = contentPropertyMap.get(index); ExcelContentProperty excelContentProperty = contentPropertyMap.get(index);
Object value = convertValue(cellData, excelContentProperty.getField().getType(), excelContentProperty, Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField().getType(),
currentReadHolder.converterMap(), currentReadHolder.globalConfiguration()); excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration());
if (value != null) { if (value != null) {
map.put(excelContentProperty.getField().getName(), value); map.put(excelContentProperty.getField().getName(), value);
} }
@ -100,29 +104,6 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
return resultModel; return resultModel;
} }
private Object convertValue(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration) {
if (clazz == CellData.class) {
return new CellData(cellData);
}
Converter converter = null;
if (contentProperty != null) {
converter = contentProperty.getConverter();
}
if (converter == null) {
converter = converterMap.get(ConverterKeyBuild.buildKey(clazz, cellData.getType()));
}
if (converter == null) {
throw new ExcelDataConvertException(
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
}
try {
return converter.convertToJavaData(cellData, contentProperty, globalConfiguration);
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to " + clazz + " error ", e);
}
}
@Override @Override
public void doAfterAllAnalysed(AnalysisContext context) {} public void doAfterAllAnalysed(AnalysisContext context) {}
} }

13
src/main/java/com/alibaba/excel/read/listener/ReadListener.java

@ -1,7 +1,10 @@
package com.alibaba.excel.read.listener; package com.alibaba.excel.read.listener;
import java.util.Map;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.Listener; import com.alibaba.excel.event.Listener;
import com.alibaba.excel.metadata.CellData;
/** /**
* Interface to listen for read results * Interface to listen for read results
@ -20,7 +23,15 @@ public interface ReadListener<T> extends Listener {
void onException(Exception exception, AnalysisContext context) throws Exception; void onException(Exception exception, AnalysisContext context) throws Exception;
/** /**
* when analysis one row trigger invoke function. * When analysis one head row trigger invoke function.
*
* @param headMap
* @param context
*/
void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context);
/**
* When analysis one row trigger invoke function.
* *
* @param data * @param data
* one row value. Is is same as {@link AnalysisContext#readRowHolder()} * one row value. Is is same as {@link AnalysisContext#readRowHolder()}

57
src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java

@ -26,6 +26,7 @@ import com.alibaba.excel.read.listener.ReadListenerRegistryCenter;
import com.alibaba.excel.read.listener.event.AnalysisFinishEvent; import com.alibaba.excel.read.listener.event.AnalysisFinishEvent;
import com.alibaba.excel.read.metadata.ReadBasicParameter; import com.alibaba.excel.read.metadata.ReadBasicParameter;
import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty;
import com.alibaba.excel.util.ConverterUtils;
import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.util.StringUtils;
/** /**
@ -118,8 +119,11 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
Map<Integer, CellData> cellDataMap = event.getAnalysisResult(); Map<Integer, CellData> cellDataMap = event.getAnalysisResult();
ReadRowHolder readRowHolder = analysisContext.readRowHolder(); ReadRowHolder readRowHolder = analysisContext.readRowHolder();
readRowHolder.setCurrentRowAnalysisResult(cellDataMap); readRowHolder.setCurrentRowAnalysisResult(cellDataMap);
int rowIndex = readRowHolder.getRowIndex();
int headRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();
if (readRowHolder.getRowIndex() >= analysisContext.readSheetHolder().getHeadRowNumber()) { if (rowIndex >= headRowNumber) {
// Now is data
for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) { for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
try { try {
readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext); readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);
@ -136,11 +140,29 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
throw new ExcelAnalysisStopException(); throw new ExcelAnalysisStopException();
} }
} }
return; } else {
// Last head column
if (headRowNumber == rowIndex + 1) {
buildHead(analysisContext, cellDataMap);
} }
// Now is header // Now is header
if (analysisContext.readSheetHolder().getHeadRowNumber().equals(readRowHolder.getRowIndex() + 1)) { for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
buildHead(analysisContext, cellDataMap); try {
readListener.invokeHead(cellDataMap, analysisContext);
} catch (Exception e) {
for (ReadListener readListenerException : analysisContext.currentReadHolder().readListenerList()) {
try {
readListenerException.onException(e, analysisContext);
} catch (Exception exception) {
throw new ExcelAnalysisException("Listen error!", exception);
}
}
}
if (!readListener.hasNext(analysisContext)) {
throw new ExcelAnalysisStopException();
}
}
} }
} }
@ -155,7 +177,8 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
if (!HeadKindEnum.CLASS.equals(analysisContext.currentReadHolder().excelReadHeadProperty().getHeadKind())) { if (!HeadKindEnum.CLASS.equals(analysisContext.currentReadHolder().excelReadHeadProperty().getHeadKind())) {
return; return;
} }
Map<Integer, String> dataMap = buildStringMap(cellDataMap, analysisContext.currentReadHolder()); Map<Integer, String> dataMap =
ConverterUtils.convertToStringMap(cellDataMap, analysisContext.currentReadHolder());
ExcelReadHeadProperty excelHeadPropertyData = analysisContext.readSheetHolder().excelReadHeadProperty(); ExcelReadHeadProperty excelHeadPropertyData = analysisContext.readSheetHolder().excelReadHeadProperty();
Map<Integer, Head> headMapData = excelHeadPropertyData.getHeadMap(); Map<Integer, Head> headMapData = excelHeadPropertyData.getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMapData = excelHeadPropertyData.getContentPropertyMap(); Map<Integer, ExcelContentProperty> contentPropertyMapData = excelHeadPropertyData.getContentPropertyMap();
@ -192,30 +215,6 @@ public abstract class AbstractReadHolder extends AbstractHolder implements ReadH
excelHeadPropertyData.setContentPropertyMap(tmpContentPropertyMap); excelHeadPropertyData.setContentPropertyMap(tmpContentPropertyMap);
} }
private Map<Integer, String> buildStringMap(Map<Integer, CellData> cellDataMap, ReadHolder readHolder) {
Map<Integer, String> stringMap = new HashMap<Integer, String>(cellDataMap.size() * 4 / 3 + 1);
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
CellData cellData = entry.getValue();
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
stringMap.put(entry.getKey(), null);
continue;
}
Converter converter =
readHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType()));
if (converter == null) {
throw new ExcelDataConvertException(
"Converter not found, convert " + cellData.getType() + " to String");
}
try {
stringMap.put(entry.getKey(),
(String)(converter.convertToJavaData(cellData, null, readHolder.globalConfiguration())));
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to String error ", e);
}
}
return stringMap;
}
public List<ReadListener> getReadListenerList() { public List<ReadListener> getReadListenerList() {
return readListenerList; return readListenerList;
} }

87
src/main/java/com/alibaba/excel/util/ConverterUtils.java

@ -0,0 +1,87 @@
package com.alibaba.excel.util;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKeyBuild;
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.property.ExcelContentProperty;
import com.alibaba.excel.read.metadata.holder.ReadHolder;
/**
* Converting objects
*
* @author Jiaju Zhuang
**/
public class ConverterUtils {
private ConverterUtils() {}
/**
* Convert it into a String map
*
* @param cellDataMap
* @param readHolder
* @return
*/
public static Map<Integer, String> convertToStringMap(Map<Integer, CellData> cellDataMap, ReadHolder readHolder) {
Map<Integer, String> stringMap = new HashMap<Integer, String>(cellDataMap.size() * 4 / 3 + 1);
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
CellData cellData = entry.getValue();
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
stringMap.put(entry.getKey(), null);
continue;
}
Converter converter =
readHolder.converterMap().get(ConverterKeyBuild.buildKey(String.class, cellData.getType()));
if (converter == null) {
throw new ExcelDataConvertException(
"Converter not found, convert " + cellData.getType() + " to String");
}
try {
stringMap.put(entry.getKey(),
(String)(converter.convertToJavaData(cellData, null, readHolder.globalConfiguration())));
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to String error ", e);
}
}
return stringMap;
}
/**
* Convert it into a Java object
*
* @param cellData
* @param clazz
* @param contentProperty
* @param converterMap
* @param globalConfiguration
* @return
*/
public static Object convertToJavaObject(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<String, Converter> converterMap, GlobalConfiguration globalConfiguration) {
if (clazz == CellData.class) {
return new CellData(cellData);
}
Converter converter = null;
if (contentProperty != null) {
converter = contentProperty.getConverter();
}
if (converter == null) {
converter = converterMap.get(ConverterKeyBuild.buildKey(clazz, cellData.getType()));
}
if (converter == null) {
throw new ExcelDataConvertException(
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
}
try {
return converter.convertToJavaData(cellData, contentProperty, globalConfiguration);
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to " + clazz + " error ", e);
}
}
}

4
src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java

@ -27,12 +27,12 @@ public class AnnotationDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() throws Exception { public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() throws Exception { public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03); readAndWrite(file03);
} }

4
src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationIndexAndNameDataTest.java

@ -27,12 +27,12 @@ public class AnnotationIndexAndNameDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() { public void t01ReadAndWrite07() {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() { public void t02ReadAndWrite03() {
readAndWrite(file03); readAndWrite(file03);
} }

4
src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityDataTest.java

@ -42,12 +42,12 @@ public class CompatibilityDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() throws Exception { public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() throws Exception { public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03); readAndWrite(file03);
} }

2
src/test/java/com/alibaba/easyexcel/test/core/compatibility/CompatibilityParameterDataTest.java

@ -31,7 +31,7 @@ public class CompatibilityParameterDataTest {
} }
@Test @Test
public void T01ReadAndWrite() throws Exception { public void t01ReadAndWrite() throws Exception {
readAndWrite1(file); readAndWrite1(file);
readAndWrite2(file); readAndWrite2(file);
readAndWrite3(file); readAndWrite3(file);

12
src/test/java/com/alibaba/easyexcel/test/core/converter/ConverterDataTest.java

@ -38,12 +38,12 @@ public class ConverterDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() throws Exception { public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() throws Exception { public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03); readAndWrite(file03);
} }
@ -53,22 +53,22 @@ public class ConverterDataTest {
} }
@Test @Test
public void T03ReadAllConverter07() { public void t03ReadAllConverter07() {
readAllConverter("converter" + File.separator + "converter07.xlsx"); readAllConverter("converter" + File.separator + "converter07.xlsx");
} }
@Test @Test
public void T04ReadAllConverter03() { public void t04ReadAllConverter03() {
readAllConverter("converter" + File.separator + "converter03.xls"); readAllConverter("converter" + File.separator + "converter03.xls");
} }
@Test @Test
public void T05WriteImage07() throws Exception { public void t05WriteImage07() throws Exception {
writeImage(fileImage07); writeImage(fileImage07);
} }
@Test @Test
public void T06WriteImage03() throws Exception { public void t06WriteImage03() throws Exception {
writeImage(fileImage03); writeImage(fileImage03);
} }

4
src/test/java/com/alibaba/easyexcel/test/core/exception/ExceptionDataTest.java

@ -31,12 +31,12 @@ public class ExceptionDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() throws Exception { public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() throws Exception { public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03); readAndWrite(file03);
} }

4
src/test/java/com/alibaba/easyexcel/test/core/head/ComplexHeadDataTest.java

@ -26,12 +26,12 @@ public class ComplexHeadDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() { public void t01ReadAndWrite07() {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() { public void t02ReadAndWrite03() {
readAndWrite(file03); readAndWrite(file03);
} }

4
src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataTest.java

@ -28,12 +28,12 @@ public class ListHeadDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() throws Exception { public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() throws Exception { public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03); readAndWrite(file03);
} }

4
src/test/java/com/alibaba/easyexcel/test/core/head/NoHeadDataTest.java

@ -26,12 +26,12 @@ public class NoHeadDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() { public void t01ReadAndWrite07() {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() { public void t02ReadAndWrite03() {
readAndWrite(file03); readAndWrite(file03);
} }

2
src/test/java/com/alibaba/easyexcel/test/core/parameter/ParameterDataTest.java

@ -35,7 +35,7 @@ public class ParameterDataTest {
} }
@Test @Test
public void T01ReadAndWrite() throws Exception { public void t01ReadAndWrite() throws Exception {
readAndWrite1(); readAndWrite1();
readAndWrite2(); readAndWrite2();
readAndWrite3(); readAndWrite3();

8
src/test/java/com/alibaba/easyexcel/test/core/repetition/RepetitionDataTest.java

@ -38,12 +38,12 @@ public class RepetitionDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() { public void t01ReadAndWrite07() {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() { public void t02ReadAndWrite03() {
readAndWrite(file03); readAndWrite(file03);
} }
@ -57,12 +57,12 @@ public class RepetitionDataTest {
} }
@Test @Test
public void T03ReadAndWriteTable07() { public void t03ReadAndWriteTable07() {
readAndWriteTable(fileTable07); readAndWriteTable(fileTable07);
} }
@Test @Test
public void T04ReadAndWriteTable03() { public void t04ReadAndWriteTable03() {
readAndWriteTable(fileTable03); readAndWriteTable(fileTable03);
} }

7
src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataListener.java

@ -2,6 +2,7 @@ package com.alibaba.easyexcel.test.core.simple;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import org.junit.Assert; import org.junit.Assert;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -18,6 +19,12 @@ public class SimpleDataListener extends AnalysisEventListener<SimpleData> {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleDataListener.class); private static final Logger LOGGER = LoggerFactory.getLogger(SimpleDataListener.class);
List<SimpleData> list = new ArrayList<SimpleData>(); List<SimpleData> list = new ArrayList<SimpleData>();
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
LOGGER.debug("Head is:{}", JSON.toJSONString(headMap));
Assert.assertEquals(headMap.get(0), "姓名");
}
@Override @Override
public void invoke(SimpleData data, AnalysisContext context) { public void invoke(SimpleData data, AnalysisContext context) {
list.add(data); list.add(data);

10
src/test/java/com/alibaba/easyexcel/test/core/simple/SimpleDataTest.java

@ -30,12 +30,12 @@ public class SimpleDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() { public void t01ReadAndWrite07() {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() { public void t02ReadAndWrite03() {
readAndWrite(file03); readAndWrite(file03);
} }
@ -45,17 +45,17 @@ public class SimpleDataTest {
} }
@Test @Test
public void T03SynchronousRead07() { public void t03SynchronousRead07() {
synchronousRead(file07); synchronousRead(file07);
} }
@Test @Test
public void T04SynchronousRead03() { public void t04SynchronousRead03() {
synchronousRead(file03); synchronousRead(file03);
} }
@Test @Test
public void T05SheetNameRead07() { public void t05SheetNameRead07() {
EasyExcel.read(TestFileUtil.readFile("simple" + File.separator + "simple07.xlsx"), SimpleData.class, EasyExcel.read(TestFileUtil.readFile("simple" + File.separator + "simple07.xlsx"), SimpleData.class,
new SimpleDataSheetNameListener()).sheet("simple").doRead(); new SimpleDataSheetNameListener()).sheet("simple").doRead();
} }

8
src/test/java/com/alibaba/easyexcel/test/core/style/StyleDataTest.java

@ -44,17 +44,17 @@ public class StyleDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() { public void t01ReadAndWrite07() {
readAndWrite(file07); readAndWrite(file07);
} }
@Test @Test
public void T02ReadAndWrite03() { public void t02ReadAndWrite03() {
readAndWrite(file03); readAndWrite(file03);
} }
@Test @Test
public void T03AbstractVerticalCellStyleStrategy() { public void t03AbstractVerticalCellStyleStrategy() {
AbstractVerticalCellStyleStrategy verticalCellStyleStrategy = new AbstractVerticalCellStyleStrategy() { AbstractVerticalCellStyleStrategy verticalCellStyleStrategy = new AbstractVerticalCellStyleStrategy() {
@Override @Override
protected WriteCellStyle headCellStyle(Head head) { protected WriteCellStyle headCellStyle(Head head) {
@ -112,7 +112,7 @@ public class StyleDataTest {
} }
@Test @Test
public void T04LoopMergeStrategy() { public void t04LoopMergeStrategy() {
EasyExcel.write(file07, StyleData.class).sheet().registerWriteHandler(new LoopMergeStrategy(2, 1)) EasyExcel.write(file07, StyleData.class).sheet().registerWriteHandler(new LoopMergeStrategy(2, 1))
.doWrite(data10()); .doWrite(data10());
} }

4
src/test/java/com/alibaba/easyexcel/test/core/template/TemplateDataTest.java

@ -29,12 +29,12 @@ public class TemplateDataTest {
} }
@Test @Test
public void T01ReadAndWrite07() { public void t01ReadAndWrite07() {
readAndWrite07(file07); readAndWrite07(file07);
} }
@Test @Test
public void T02ReadAndWrite03() { public void t02ReadAndWrite03() {
readAndWrite03(file03); readAndWrite03(file03);
} }

73
src/test/java/com/alibaba/easyexcel/test/demo/read/DemoHeadDataListener.java

@ -0,0 +1,73 @@
package com.alibaba.easyexcel.test.demo.read;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.fastjson.JSON;
/**
* 读取头
*
* @author Jiaju Zhuang
*/
public class DemoHeadDataListener extends AnalysisEventListener<DemoData> {
private static final Logger LOGGER = LoggerFactory.getLogger(DemoHeadDataListener.class);
/**
* 每隔5条存储数据库实际使用中可以3000条然后清理list 方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<DemoData> list = new ArrayList<DemoData>();
/**
* 在转换异常 获取其他异常下会调用本接口抛出异常则停止读取如果这里不抛出异常则 继续读取下一行
*
* @param exception
* @param context
* @throws Exception
*/
@Override
public void onException(Exception exception, AnalysisContext context) {
LOGGER.error("解析失败,但是继续解析下一行", exception);
}
/**
* 这里会一行行的返回头
*
* @param headMap
* @param context
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
}
@Override
public void invoke(DemoData data, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
if (list.size() >= BATCH_COUNT) {
saveData();
list.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
LOGGER.info("存储数据库成功!");
}
}

34
src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java

@ -134,6 +134,40 @@ public class ReadTest {
.headRowNumber(1).doRead(); .headRowNumber(1).doRead();
} }
/**
* 读取表头数据
*
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData}
* <p>
* 2. 由于默认异步读取excel所以需要创建excel一行一行的回调监听器参照{@link DemoHeadDataListener}
* <p>
* 3. 直接读即可
*/
@Test
public void headerRead() {
String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 然后千万别忘记 finish
EasyExcel.read(fileName, DemoData.class, new DemoHeadDataListener()).sheet().doRead();
}
/**
* 数据转换等异常处理
*
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData}
* <p>
* 2. 由于默认异步读取excel所以需要创建excel一行一行的回调监听器参照{@link DemoHeadDataListener}
* <p>
* 3. 直接读即可
*/
@Test
public void exceptionRead() {
String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 然后千万别忘记 finish
EasyExcel.read(fileName, DemoData.class, new DemoHeadDataListener()).sheet().doRead();
}
/** /**
* 同步的返回不推荐使用如果数据量大会把数据放到内存里面 * 同步的返回不推荐使用如果数据量大会把数据放到内存里面
*/ */

4
update.md

@ -1,3 +1,7 @@
# 2.0.0-beta3
* 导出完成移除临时目录 [Issue #386](https://github.com/alibaba/easyexcel/issues/386)
* 新增读取返回头数据
# 2.0.0-beta2 # 2.0.0-beta2
* 加速gc回收 [Issue #511](https://github.com/alibaba/easyexcel/issues/511) * 加速gc回收 [Issue #511](https://github.com/alibaba/easyexcel/issues/511)
* 修改空字符串读取可能读取上个字段的数据的bug * 修改空字符串读取可能读取上个字段的数据的bug

Loading…
Cancel
Save