Browse Source

优化读文件逻辑

pull/507/head
zhuangjiaju 5 years ago
parent
commit
c8d64352d6
  1. 187
      src/main/java/com/alibaba/excel/ExcelReader.java
  2. 4
      src/main/java/com/alibaba/excel/ExcelWriter.java
  3. 112
      src/main/java/com/alibaba/excel/analysis/BaseSaxAnalyser.java
  4. 22
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java
  5. 107
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
  6. 18
      src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java
  7. 65
      src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
  8. 10
      src/main/java/com/alibaba/excel/analysis/v07/SharedStringsTableHandler.java
  9. 19
      src/main/java/com/alibaba/excel/analysis/v07/XlsxHandlerFactory.java
  10. 6
      src/main/java/com/alibaba/excel/analysis/v07/XlsxRowHandler.java
  11. 222
      src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
  12. 11
      src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java
  13. 22
      src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java
  14. 27
      src/main/java/com/alibaba/excel/cache/Cache.java
  15. 4
      src/main/java/com/alibaba/excel/cache/Ehcache.java
  16. 15
      src/main/java/com/alibaba/excel/cache/Ehcache2.java
  17. 2
      src/main/java/com/alibaba/excel/cache/EhcacheFile.java
  18. 2
      src/main/java/com/alibaba/excel/cache/EhcacheMix.java
  19. 34
      src/main/java/com/alibaba/excel/cache/ReadCache.java
  20. 4
      src/main/java/com/alibaba/excel/cache/SharedStringsTableReadCache.java
  21. 116
      src/main/java/com/alibaba/excel/context/AnalysisContext.java
  22. 193
      src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java
  23. 4
      src/main/java/com/alibaba/excel/context/WriteContext.java
  24. 54
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  25. 9
      src/main/java/com/alibaba/excel/converters/ConverterRegistryCenter.java
  26. 8
      src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java
  27. 4
      src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java
  28. 2
      src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java
  29. 8
      src/main/java/com/alibaba/excel/event/AnalysisEventListener.java
  30. 35
      src/main/java/com/alibaba/excel/event/AnalysisEventRegistryCenter.java
  31. 1
      src/main/java/com/alibaba/excel/event/EachRowAnalysisFinishEvent.java
  32. 81
      src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java
  33. 26
      src/main/java/com/alibaba/excel/metadata/BasicParameter.java
  34. 13
      src/main/java/com/alibaba/excel/metadata/Head.java
  35. 43
      src/main/java/com/alibaba/excel/metadata/Workbook.java
  36. 204
      src/main/java/com/alibaba/excel/metadata/holder/AbstractWriteConfiguration.java
  37. 39
      src/main/java/com/alibaba/excel/metadata/holder/ReadConfiguration.java
  38. 114
      src/main/java/com/alibaba/excel/metadata/holder/SheetHolder.java
  39. 54
      src/main/java/com/alibaba/excel/metadata/holder/TableHolder.java
  40. 219
      src/main/java/com/alibaba/excel/metadata/holder/WorkbookHolder.java
  41. 4
      src/main/java/com/alibaba/excel/metadata/holder/WriteConfiguration.java
  42. 14
      src/main/java/com/alibaba/excel/metadata/property/ExcelContentProperty.java
  43. 60
      src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java
  44. 21
      src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java
  45. 98
      src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java
  46. 19
      src/main/java/com/alibaba/excel/read/listener/ReadListener.java
  47. 35
      src/main/java/com/alibaba/excel/read/listener/ReadListenerRegistryCenter.java
  48. 41
      src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java
  49. 45
      src/main/java/com/alibaba/excel/util/FileUtils.java
  50. 2
      src/main/java/com/alibaba/excel/util/NumberUtils.java
  51. 28
      src/main/java/com/alibaba/excel/util/WorkBookUtil.java
  52. 34
      src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java
  53. 22
      src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java

187
src/main/java/com/alibaba/excel/ExcelReader.java

@ -3,11 +3,16 @@ package com.alibaba.excel;
import java.io.InputStream;
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.ExcelExecutor;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.parameter.AnalysisParam;
import com.alibaba.excel.support.ExcelTypeEnum;
@ -18,34 +23,42 @@ import com.alibaba.excel.support.ExcelTypeEnum;
* @author jipengfei
*/
public class ExcelReader {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelReader.class);
/**
* Analyser
*/
private ExcelAnalyser analyser;
private ExcelAnalyser excelAnalyser;
private boolean finished = false;
/**
* Create new reader
*
* @param in the POI filesystem that contains the Workbook stream
* @param excelTypeEnum 03 or 07
* @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.
* {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @param eventListener
* Callback method after each row is parsed.
*/
@Deprecated
public ExcelReader(InputStream in, ExcelTypeEnum excelTypeEnum, Object customContent,
AnalysisEventListener eventListener) {
AnalysisEventListener eventListener) {
this(in, excelTypeEnum, customContent, eventListener, true);
}
/**
* Create new reader
*
* @param in the POI filesystem that contains the Workbook stream
* @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
* {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @param eventListener
* Callback method after each row is parsed
*/
public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener) {
this(in, customContent, eventListener, null, true);
@ -54,21 +67,25 @@ public class ExcelReader {
/**
* Create new reader
*
* @param in the POI filesystem that contains the Workbook stream
* @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
* {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @param eventListener
* Callback method after each row is parsed
*/
public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener,
List<Converter> converters) {
List<Converter> converters) {
this(in, customContent, eventListener, converters, true);
}
/**
* Create new reader
*
* @param param old param Deprecated
* @param eventListener Callback method after each row is parsed.
* @param param
* old param Deprecated
* @param eventListener
* Callback method after each row is parsed.
*/
@Deprecated
public ExcelReader(AnalysisParam param, AnalysisEventListener eventListener) {
@ -78,19 +95,22 @@ public class ExcelReader {
/**
* Create new reader
*
* @param in the POI filesystem that contains the Workbook stream
* @param excelTypeEnum 03 or 07
* @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.
* {@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
public ExcelReader(InputStream in, ExcelTypeEnum excelTypeEnum, Object customContent,
AnalysisEventListener eventListener, boolean trim) {
AnalysisEventListener eventListener, boolean trim) {
this(in, excelTypeEnum, customContent, eventListener, null, trim);
}
@ -99,31 +119,30 @@ public class ExcelReader {
*
* @param in
* @param customContent
* {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* {@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.
* @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.
*/
public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener,
List<Converter> converters, boolean trim) {
List<Converter> converters, boolean trim) {
this(in, ExcelTypeEnum.valueOf(in), customContent, eventListener, converters, trim);
}
public ExcelReader(InputStream in, Object excelTypeEnum, AnalysisEventListener<Object> eventListener,
boolean trim) {
boolean trim) {
this(in, ExcelTypeEnum.valueOf(in), null, eventListener, null, trim);
}
public ExcelReader(InputStream in, ExcelTypeEnum excelTypeEnum, Object customContent,
AnalysisEventListener eventListener, List<Converter> converters, boolean trim) {
AnalysisEventListener eventListener, List<Converter> converters, boolean trim) {
validateParam(in, eventListener);
analyser = new ExcelAnalyserImpl(in, excelTypeEnum, customContent, eventListener, trim);
initConverters(analyser, converters);
}
private void initConverters(ExcelAnalyser analyser, List<Converter> converters) {
if (converters != null && converters.size() > 0) {
for (Converter c : converters) {
@ -136,58 +155,118 @@ public class ExcelReader {
* Parse all sheet content by default
*/
public void read() {
read(null, null);;
ExcelExecutor excelExecutor = excelAnalyser.excelExecutor();
if (excelExecutor.sheetList().isEmpty()) {
LOGGER.warn("Excel doesn't have any sheets.");
return;
}
for (Sheet sheet : excelExecutor.sheetList()) {
read(sheet);
}
}
/**
* Parse the specified sheetSheetNo start from 1
*
* @param sheet Read sheet
* @param sheet
* Read sheet
*/
public void read(Sheet sheet) {
read(sheet, null);
checkFinished();
excelAnalyser.analysis(sheet);
}
/**
* Parse the specified sheet
*
* @param sheet Read sheet
* @param clazz object parsed into each row of value
* @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) {
analyser.beforeAnalysis();
if (sheet != null) {
sheet.setClazz(clazz);
analyser.analysis(sheet);
} else {
analyser.analysis();
}
read(sheet);
}
/**
* Context for the entire execution process
*
* @return
*/
public AnalysisContext analysisContext() {
checkFinished();
return excelAnalyser.analysisContext();
}
/**
* Current executor
*
* @return
*/
public ExcelExecutor excelExecutor() {
checkFinished();
return excelAnalyser.excelExecutor();
}
/**
* Parse the workBook get all sheets
*
* @return workBook all sheets
*
* @deprecated please use {@link #excelExecutor()}
*/
@Deprecated
public List<Sheet> getSheets() {
return analyser.getSheets();
return excelExecutor().sheetList();
}
/**
*
* @return
* @deprecated please use {@link #analysisContext()}
*/
@Deprecated
public AnalysisContext getAnalysisContext() {
return analyser.getAnalysisContext();
return analysisContext();
}
/**
* validate param
*
* @param in
* @param eventListener
* Complete the entire read file.Release the cache and close stream.
*/
private void validateParam(InputStream in, AnalysisEventListener eventListener) {
// if (eventListener == null) {
// throw new IllegalArgumentException("AnalysisEventListener can not null");
// } else if (in == null) {
// throw new IllegalArgumentException("InputStream can not null");
// }
public void finish() {
if (finished) {
return;
}
finished = true;
excelAnalyser.finish();
}
/**
* Prevents calls to {@link #finish} from freeing the cache
*
* @throws Throwable
*/
@Override
protected void finalize() {
if (finished) {
return;
}
try {
excelAnalyser.finish();
} catch (Exception e) {
LOGGER.warn("Destroy object failed", e);
}
}
private void checkFinished() {
if (finished) {
throw new ExcelAnalysisException("Can not use a finished reader.");
}
}
}

4
src/main/java/com/alibaba/excel/ExcelWriter.java

@ -48,7 +48,7 @@ public class ExcelWriter {
public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum excelType,
boolean needHead, Map<Class, Converter> customConverterMap, List<WriteHandler> customWriteHandlerList) {
Workbook workbook = new Workbook();
workbook.setTemplateInputStream(templateInputStream);
workbook.setInputStream(templateInputStream);
workbook.setOutputStream(outputStream);
workbook.setExcelType(excelType);
workbook.setNeedHead(needHead);
@ -135,7 +135,7 @@ public class ExcelWriter {
List<WriteHandler> customWriteHandlerList = new ArrayList<WriteHandler>();
customWriteHandlerList.add(writeHandler);
Workbook workbook = new Workbook();
workbook.setTemplateInputStream(templateInputStream);
workbook.setInputStream(templateInputStream);
workbook.setOutputStream(outputStream);
workbook.setExcelType(typeEnum);
workbook.setNeedHead(needHead);

112
src/main/java/com/alibaba/excel/analysis/BaseSaxAnalyser.java

@ -1,112 +0,0 @@
package com.alibaba.excel.analysis;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.converters.DefaultConverterLoader;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
import com.alibaba.excel.event.AnalysisFinishEvent;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import com.alibaba.excel.metadata.Sheet;
/**
* @author jipengfei
*/
public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, AnalysisEventRegistryCenter, ExcelAnalyser {
protected AnalysisContext analysisContext;
private LinkedHashMap<String, AnalysisEventListener<Object>> listeners =
new LinkedHashMap<String, AnalysisEventListener<Object>>();
private Map<ConverterKey, Converter> converters = new HashMap<ConverterKey, Converter>();
/**
* execute method
*/
protected abstract void execute();
@Override
public void register(String name, AnalysisEventListener<Object> listener) {
if (!listeners.containsKey(name)) {
listeners.put(name, listener);
}
}
@Override
public void register(Converter converter) {
converters.put(new ConverterKey(converter.supportJavaTypeKey(),converter.supportExcelTypeKey()), converter);
}
@Override
public void beforeAnalysis() {
registerDefaultConverters();
}
private void registerDefaultConverters() {
converters.putAll(DefaultConverterLoader.loadDefaultReadConverter());
}
@Override
public Map<ConverterKey, Converter> getConverters() {
return converters;
}
@Override
public void analysis(Sheet sheetParam) {
analysisContext.setCurrentSheet(sheetParam);
execute();
}
@Override
public void analysis() {
execute();
}
@Override
public AnalysisContext getAnalysisContext() {
return analysisContext;
}
/**
*/
@Override
public void cleanAllListeners() {
listeners.clear();
}
@Override
public void cleanListener(String name) {
listeners.remove(name);
}
@SuppressWarnings("unchecked")
@Override
public void notify(AnalysisFinishEvent event) {
analysisContext.setCurrentRowAnalysisResult(event.getAnalysisResult());
/** Parsing header content **/
if (analysisContext.getCurrentRowNum() < analysisContext.getCurrentSheet().getReadHeadRowNumber()) {
if (analysisContext.getCurrentRowNum() <= analysisContext.getCurrentSheet().getReadHeadRowNumber() - 1) {
buildExcelHeadProperty(null, (List<String>)analysisContext.getCurrentRowAnalysisResult());
}
} else {
for (Entry<String, AnalysisEventListener<Object>> entry : listeners.entrySet()) {
entry.getValue().invoke(analysisContext.getCurrentRowAnalysisResult(), analysisContext);
}
}
}
private void buildExcelHeadProperty(Class clazz, List<String> headOneRow) {
ExcelHeadProperty excelHeadProperty =
ExcelHeadProperty.buildExcelHeadProperty(this.analysisContext.getExcelHeadProperty(), clazz, headOneRow);
this.analysisContext.setExcelHeadProperty(excelHeadProperty);
}
}

22
src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java

@ -1,7 +1,5 @@
package com.alibaba.excel.analysis;
import java.util.List;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.Sheet;
@ -11,9 +9,6 @@ import com.alibaba.excel.metadata.Sheet;
* @author jipengfei
*/
public interface ExcelAnalyser {
void beforeAnalysis();
/**
* parse one sheet
*
@ -22,21 +17,22 @@ public interface ExcelAnalyser {
void analysis(Sheet sheetParam);
/**
* parse all sheets
* Complete the entire read file.Release the cache and close stream
*/
void analysis();
void finish();
/**
* get all sheet of workbook
*
* @return all sheets
* Acquisition excel executor
*
* @return
*/
List<Sheet> getSheets();
ExcelExecutor excelExecutor();
/**
* get the analysis context.
*
* @return analysis context
*/
AnalysisContext getAnalysisContext();
AnalysisContext analysisContext();
}

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

@ -1,21 +1,12 @@
package com.alibaba.excel.analysis;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
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.AnalysisContextImpl;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.event.ModelBuildEventListener;
import com.alibaba.excel.metadata.Workbook;
import com.alibaba.excel.support.ExcelTypeEnum;
/**
@ -25,93 +16,49 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
private AnalysisContext analysisContext;
private BaseSaxAnalyser saxAnalyser;
public ExcelAnalyserImpl(InputStream inputStream, ExcelTypeEnum excelTypeEnum, Object custom,
AnalysisEventListener<Object> eventListener, boolean trim) {
ConverterRegistryCenter center = new ConverterRegistryCenter() {
@Override
public void register(Converter converter) {
saxAnalyser.register(converter);
}
private ExcelExecutor excelExecutor;
@Override
public Map<ConverterKey, Converter> getConverters() {
return saxAnalyser.getConverters();
}
};
analysisContext = new AnalysisContextImpl(inputStream, excelTypeEnum, custom,
eventListener, center, trim);
this.saxAnalyser = getSaxAnalyser();
public ExcelAnalyserImpl(Workbook workbook) {
analysisContext = new AnalysisContextImpl(workbook);
choiceExcelExecutor();
}
private BaseSaxAnalyser getSaxAnalyser() {
if (saxAnalyser != null) {
return this.saxAnalyser;
}
private void choiceExcelExecutor() {
try {
if (analysisContext.getExcelType() != null) {
switch (analysisContext.getExcelType()) {
case XLS:
this.saxAnalyser = new XlsSaxAnalyser(analysisContext);
break;
case XLSX:
this.saxAnalyser = new XlsxSaxAnalyser(analysisContext);
break;
}
} else {
try {
this.saxAnalyser = new XlsxSaxAnalyser(analysisContext);
} catch (Exception e) {
if (!analysisContext.getInputStream().markSupported()) {
throw new ExcelAnalysisException(
"Xls must be available markSupported,you can do like this <code> new "
+ "BufferedInputStream(new FileInputStream(\"/xxxx\"))</code> ");
}
this.saxAnalyser = new XlsSaxAnalyser(analysisContext);
}
ExcelTypeEnum excelType = analysisContext.currentWorkbookHolder().getExcelType();
if (excelType == null) {
excelExecutor = new XlsxSaxAnalyser(analysisContext);
return;
}
switch (excelType) {
case XLS:
excelExecutor = new XlsSaxAnalyser(analysisContext);
break;
case XLSX:
excelExecutor = new XlsxSaxAnalyser(analysisContext);
break;
default:
}
} catch (Exception e) {
throw new ExcelAnalysisException("File type error,io must be available markSupported,you can do like "
+ "this <code> new BufferedInputStream(new FileInputStream(\\\"/xxxx\\\"))</code> \"", e);
}
return this.saxAnalyser;
}
@Override
public void analysis(Sheet sheetParam) {
analysisContext.setCurrentSheet(sheetParam);
analysis();
}
@Override
public AnalysisContext getAnalysisContext() {
return analysisContext;
}
@Override
public void analysis() {
saxAnalyser.execute();
public void analysis(Sheet sheet) {
analysisContext.currentSheet(sheet);
excelExecutor.execute();
analysisContext.getEventListener().doAfterAllAnalysed(analysisContext);
}
@Override
public List<Sheet> getSheets() {
return this.saxAnalyser.getSheets();
}
private void registerListeners(BaseSaxAnalyser saxAnalyser) {
saxAnalyser.cleanAllListeners();
if (analysisContext.getCurrentSheet() != null && analysisContext.getCurrentSheet().getClazz() != null) {
saxAnalyser.register("model_build_listener", new ModelBuildEventListener(this.saxAnalyser.getConverters()));
}
if (analysisContext.getEventListener() != null) {
saxAnalyser.register("user_define_listener", analysisContext.getEventListener());
}
public com.alibaba.excel.analysis.ExcelExecutor excelExecutor() {
return excelExecutor;
}
@Override
public void beforeAnalysis() {
BaseSaxAnalyser saxAnalyser = getSaxAnalyser();
registerListeners(saxAnalyser);
public AnalysisContext analysisContext() {
return analysisContext;
}
}

18
src/main/java/com/alibaba/excel/analysis/ExcelExecutor.java

@ -0,0 +1,18 @@
package com.alibaba.excel.analysis;
import java.util.List;
import com.alibaba.excel.metadata.Sheet;
/**
* Excel file Executor
*
* @author zhuangjiaju
*/
public interface ExcelExecutor {
List<Sheet> sheetList();
void execute();
}

65
src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java

@ -1,32 +1,53 @@
package com.alibaba.excel.analysis.v03;
import com.alibaba.excel.analysis.BaseSaxAnalyser;
import com.alibaba.excel.analysis.v03.handlers.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;
import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.analysis.v03.handlers.BOFRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.BlankOrErrorRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.FormulaRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.LabelRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.MissingCellDummyRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.NoteRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.NumberRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.RKRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.SSTRecordHandler;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.EachRowAnalysisFinishEvent;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.util.CollectionUtils;
import org.apache.poi.hssf.eventusermodel.*;
import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* /** * A text extractor for Excel files. * <p> * Returns the textual content of the file, suitable for * indexing by
* something like Lucene, but not really * intended for display to the user. * </p> * <p> * To turn an excel file into
* a CSV or similar, then see * the XLS2CSVmra example * </p> * * @see
* <a href="http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java">XLS2CSVmra</a>
* /** * A text extractor for Excel files. *
* <p>
* * Returns the textual content of the file, suitable for * indexing by something like Lucene, but not really *
* intended for display to the user. *
* </p>
* *
* <p>
* * To turn an excel file into a CSV or similar, then see * the XLS2CSVmra example *
* </p>
* * * @see <a href=
* "http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java">XLS2CSVmra</a>
*
* @author jipengfei
*/
public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
public class XlsSaxAnalyser implements HSSFListener, ExcelExecutor {
private boolean outputFormulaValues = true;
private POIFSFileSystem fs;
private int lastRowNumber;
@ -41,6 +62,7 @@ public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
private List<Sheet> sheets = new ArrayList<Sheet>();
private HSSFWorkbook stubWorkbook;
private List<XlsRecordHandler> recordHandlers = new ArrayList<XlsRecordHandler>();
public XlsSaxAnalyser(AnalysisContext context) throws IOException {
this.analysisContext = context;
this.records = new ArrayList<String>();
@ -54,6 +76,11 @@ public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
return sheets;
}
@Override
public List<Sheet> sheetList() {
return null;
}
@Override
public void execute() {
MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
@ -93,7 +120,7 @@ public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
int thisRow = -1;
int thisColumn = -1;
String thisStr = null;
for(XlsRecordHandler handler : this.recordHandlers) {
for (XlsRecordHandler handler : this.recordHandlers) {
if (handler.support(record)) {
handler.processRecord(record);
thisRow = handler.getRow();
@ -162,7 +189,7 @@ public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
Collections.sort(recordHandlers);
}
for(XlsRecordHandler x : recordHandlers) {
for (XlsRecordHandler x : recordHandlers) {
x.init();
}
}

10
src/main/java/com/alibaba/excel/analysis/v07/SharedStringsTableHandler.java

@ -6,7 +6,7 @@ import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.alibaba.excel.cache.Cache;
import com.alibaba.excel.cache.ReadCache;
/**
* Sax read sharedStringsTable.xml
@ -19,10 +19,10 @@ public class SharedStringsTableHandler extends DefaultHandler {
private String currentData;
private boolean isT;
private int index = 0;
private Cache cache;
private ReadCache readCache;
public SharedStringsTableHandler(Cache cache) {
this.cache = cache;
public SharedStringsTableHandler(ReadCache readCache) {
this.readCache = readCache;
}
@Override
@ -44,7 +44,7 @@ public class SharedStringsTableHandler extends DefaultHandler {
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (isT) {
cache.put(index++, new String(ch, start, length));
readCache.put(index++, new String(ch, start, length));
if (index % 100000 == 0) {
LOGGER.info("row:{} ,mem:{},data:{}", index, Runtime.getRuntime().totalMemory());
}

19
src/main/java/com/alibaba/excel/analysis/v07/XlsxHandlerFactory.java

@ -6,23 +6,20 @@ import java.util.List;
import com.alibaba.excel.analysis.v07.handlers.CountRowCellHandler;
import com.alibaba.excel.analysis.v07.handlers.DefaultCellHandler;
import com.alibaba.excel.analysis.v07.handlers.ProcessResultCellHandler;
import com.alibaba.excel.cache.Cache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
/**
* Build handler
*
* @author Dan Zheng
*/
public class XlsxHandlerFactory {
public static List<XlsxCellHandler> buildCellHandlers(AnalysisContext analysisContext,
AnalysisEventRegistryCenter registerCenter, Cache cahe) {
public static List<XlsxCellHandler> buildCellHandlers(AnalysisContext analysisContext) {
List<XlsxCellHandler> result = new ArrayList<XlsxCellHandler>();
result.add(new CountRowCellHandler(analysisContext));
DefaultCellHandler defaultCellHandler = buildXlsxRowResultHandler(analysisContext, registerCenter, cahe);
DefaultCellHandler defaultCellHandler = new DefaultCellHandler(analysisContext);
result.add(defaultCellHandler);
result.add(new ProcessResultCellHandler(registerCenter, defaultCellHandler));
result.add(new ProcessResultCellHandler(analysisContext, defaultCellHandler));
return result;
}
private static DefaultCellHandler buildXlsxRowResultHandler(AnalysisContext analysisContext,
AnalysisEventRegistryCenter registerCenter, Cache cahe) {
return new DefaultCellHandler(analysisContext, registerCenter, cahe);
}
}

6
src/main/java/com/alibaba/excel/analysis/v07/XlsxRowHandler.java

@ -6,9 +6,7 @@ import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.alibaba.excel.cache.Cache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
/**
*
@ -19,8 +17,8 @@ public class XlsxRowHandler extends DefaultHandler {
private List<XlsxCellHandler> cellHandlers;
private XlsxRowResultHolder rowResultHolder;
public XlsxRowHandler(AnalysisEventRegistryCenter registerCenter, Cache cache, AnalysisContext analysisContext) {
this.cellHandlers = XlsxHandlerFactory.buildCellHandlers(analysisContext, registerCenter, cache);
public XlsxRowHandler(AnalysisContext analysisContext) {
this.cellHandlers = XlsxHandlerFactory.buildCellHandlers(analysisContext);
for (XlsxCellHandler cellHandler : cellHandlers) {
if (cellHandler instanceof XlsxRowResultHolder) {
this.rowResultHolder = (XlsxRowResultHolder)cellHandler;

222
src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java

@ -1,133 +1,120 @@
package com.alibaba.excel.analysis.v07;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook;
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.XMLReader;
import com.alibaba.excel.analysis.BaseSaxAnalyser;
import com.alibaba.excel.cache.Cache;
import com.alibaba.excel.cache.EhcacheFile;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.cache.Ehcache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.holder.WorkbookHolder;
import com.alibaba.excel.util.FileUtils;
/**
*
* @author jipengfei
*/
public class XlsxSaxAnalyser extends BaseSaxAnalyser {
public class XlsxSaxAnalyser implements ExcelExecutor {
private AnalysisContext analysisContext;
private List<Sheet> sheetList;
private Map<Integer, InputStream> sheetMap;
private XSSFReader xssfReader;
public XlsxSaxAnalyser(AnalysisContext analysisContext) throws Exception {
this.analysisContext = analysisContext;
analysisContext.setCurrentRowNum(0);
WorkbookHolder workbookHolder = analysisContext.currentWorkbookHolder();
if (workbookHolder.getReadCache() == null) {
workbookHolder.setReadCache(new Ehcache());
}
OPCPackage pkg = readOpcPackage(workbookHolder);
private Cache cache;
// Analysis sharedStringsTable.xml
analysisSharedStringsTable(pkg, workbookHolder);
private List<SheetSource> sheetSourceList = new ArrayList<SheetSource>();
XSSFReader xssfReader = new XSSFReader(pkg);
private boolean use1904WindowDate = false;
analysisUse1904WindowDate(xssfReader, workbookHolder);
public XlsxSaxAnalyser(AnalysisContext analysisContext) throws IOException, OpenXML4JException, XmlException {
this.analysisContext = analysisContext;
analysisContext.setCurrentRowNum(0);
// OPCPackage pkg =
// OPCPackage.open(new File("D:\\git\\easyexcel\\src\\test\\resources\\read\\large\\large07.xlsx"));
// InputStream input =
// Thread.currentThread().getContextClassLoader().getResourceAsStream("read/large/large07.xlsx");
// File ff = new File("D:\\git\\easyexcel\\src\\test\\resources\\read\\large\\large0722.xlsx");
// OutputStream os = new FileOutputStream(ff);
// int bytesRead = 0;
// byte[] buffer = new byte[8192];
// while ((bytesRead = input.read(buffer, 0, 8192)) != -1) {
// os.write(buffer, 0, bytesRead);
// }
// os.close();
// input.close();
// OPCPackage pkg = OPCPackage.open(ff);
OPCPackage pkg =
OPCPackage.open(Thread.currentThread().getContextClassLoader().getResourceAsStream("read/large/large07.xlsx"));
this.xssfReader = new XSSFReader(pkg);
ArrayList<PackagePart> parts = pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType());
PackagePart packagePart = parts.get(0);
// InputStream sheet = Thread.currentThread().getContextClassLoader()
// .getResourceAsStream("read/large/large07/xl/sharedStrings.xml");
InputStream sheet = packagePart.getInputStream();
InputSource sheetSource1 = new InputSource(sheet);
this.cache = new EhcacheFile();
try {
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
saxFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
saxFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser saxParser = saxFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
ContentHandler handler = new SharedStringsTableHandler(cache);
xmlReader.setContentHandler(handler);
xmlReader.parse(sheetSource1);
sheet.close();
} catch (Exception e) {
e.printStackTrace();
throw new ExcelAnalysisException(e);
}
cache.finish();
// this.cache=new SharedStringsTableCache(xssfReader.getSharedStringsTable());
// InputStream workbookXml = xssfReader.getWorkbookData();
// WorkbookDocument ctWorkbook = WorkbookDocument.Factory.parse(workbookXml);
// CTWorkbook wb = ctWorkbook.getWorkbook();
// CTWorkbookPr prefix = wb.getWorkbookPr();
// if (prefix != null) {
// this.use1904WindowDate = prefix.getDate1904();
// }
this.analysisContext.setUse1904WindowDate(use1904WindowDate);
// sheetSourceList.add(new SheetSource("test", Thread.currentThread().getContextClassLoader()
// .getResourceAsStream("read/large/large07/xl/worksheets/sheet1.xml")));
XSSFReader.SheetIterator ite;
sheetSourceList = new ArrayList<SheetSource>();
ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
sheetList = new ArrayList<Sheet>();
sheetMap = new HashMap<Integer, InputStream>();
XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
int index = 0;
while (ite.hasNext()) {
InputStream inputStream = ite.next();
String sheetName = ite.getSheetName();
SheetSource sheetSource = new SheetSource(sheetName, inputStream);
sheetSourceList.add(sheetSource);
Sheet sheet = new Sheet();
sheet.setSheetNo(index);
sheet.setSheetName(ite.getSheetName());
sheetList.add(sheet);
sheetMap.put(index, inputStream);
index++;
}
}
@Override
protected void execute() {
Sheet sheetParam = analysisContext.getCurrentSheet();
if (sheetParam != null && sheetParam.getSheetNo() > 0 && sheetSourceList.size() >= sheetParam.getSheetNo()) {
InputStream sheetInputStream = sheetSourceList.get(sheetParam.getSheetNo() - 1).getInputStream();
parseXmlSource(sheetInputStream);
} else {
int i = 0;
for (SheetSource sheetSource : sheetSourceList) {
i++;
analysisContext.setCurrentSheet(new Sheet(i, sheetParam.getReadHeadRowNumber()));
parseXmlSource(sheetSource.getInputStream());
}
private void analysisUse1904WindowDate(XSSFReader xssfReader, WorkbookHolder workbookHolder) throws Exception {
InputStream workbookXml = xssfReader.getWorkbookData();
WorkbookDocument ctWorkbook = WorkbookDocument.Factory.parse(workbookXml);
CTWorkbook wb = ctWorkbook.getWorkbook();
CTWorkbookPr prefix = wb.getWorkbookPr();
if (prefix != null && prefix.getDate1904()) {
workbookHolder.setUse1904windowing(Boolean.TRUE);
}
}
private void analysisSharedStringsTable(OPCPackage pkg, WorkbookHolder workbookHolder) throws Exception {
ContentHandler handler = new SharedStringsTableHandler(workbookHolder.getReadCache());
parseXmlSource(pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType()).get(0).getInputStream(),
handler);
workbookHolder.getReadCache().putFinished();
}
private OPCPackage readOpcPackage(WorkbookHolder workbookHolder) throws Exception {
if (workbookHolder.getFile() != null) {
return OPCPackage.open(workbookHolder.getFile());
}
if (workbookHolder.getMandatoryUseInputStream()) {
return OPCPackage.open(workbookHolder.getInputStream());
}
File readTempFile = FileUtils.createCacheTmpFile();
workbookHolder.setReadTempFile(readTempFile);
File tempFile = new File(readTempFile.getPath(), UUID.randomUUID().toString() + ".xlsx");
FileUtils.writeToFile(readTempFile, workbookHolder.getInputStream());
return OPCPackage.open(tempFile);
}
private void parseXmlSource(InputStream inputStream) {
InputSource sheetSource = new InputSource(inputStream);
@Override
public List<Sheet> sheetList() {
return sheetList;
}
@Override
public void execute() {
parseXmlSource(sheetMap.get(analysisContext.currentSheetHolder().getSheetNo()),
new XlsxRowHandler(analysisContext));
}
private void parseXmlSource(InputStream inputStream, ContentHandler handler) {
InputSource inputSource = new InputSource(inputStream);
try {
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
saxFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
@ -135,55 +122,20 @@ public class XlsxSaxAnalyser extends BaseSaxAnalyser {
saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
SAXParser saxParser = saxFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
ContentHandler handler = new XlsxRowHandler(this, cache, analysisContext);
xmlReader.setContentHandler(handler);
xmlReader.parse(sheetSource);
xmlReader.parse(inputSource);
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
throw new ExcelAnalysisException(e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new ExcelAnalysisException("Can not close 'inputStream'!");
}
}
}
}
@Override
public List<Sheet> getSheets() {
List<Sheet> sheets = new ArrayList<Sheet>();
int i = 1;
for (SheetSource sheetSource : sheetSourceList) {
Sheet sheet = new Sheet(i, 0);
sheet.setSheetName(sheetSource.getSheetName());
i++;
sheets.add(sheet);
}
return sheets;
}
class SheetSource {
private String sheetName;
private InputStream inputStream;
public SheetSource(String sheetName, InputStream inputStream) {
this.sheetName = sheetName;
this.inputStream = inputStream;
}
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
}
}

11
src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java

@ -13,11 +13,9 @@ import org.xml.sax.Attributes;
import com.alibaba.excel.analysis.v07.XlsxCellHandler;
import com.alibaba.excel.analysis.v07.XlsxRowResultHolder;
import com.alibaba.excel.cache.Cache;
import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.util.PositionUtils;
@ -25,8 +23,6 @@ import com.alibaba.excel.util.StringUtils;
public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder {
private final AnalysisContext analysisContext;
private final AnalysisEventRegistryCenter registerCenter;
private final Cache cahe;
private String currentTag;
private String currentCellIndex;
private int curRow;
@ -34,10 +30,8 @@ public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder
private CellData[] curRowContent = new CellData[20];
private CellData currentCellData;
public DefaultCellHandler(AnalysisContext analysisContext, AnalysisEventRegistryCenter registerCenter, Cache cahe) {
public DefaultCellHandler(AnalysisContext analysisContext) {
this.analysisContext = analysisContext;
this.registerCenter = registerCenter;
this.cahe = cahe;
}
@Override
@ -84,7 +78,8 @@ public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder
ensureSize();
// Have to go "sharedStrings.xml" and get it
if (currentCellData.getType() == CellDataTypeEnum.STRING) {
currentCellData.setStringValue(cahe.get(Integer.valueOf(currentCellData.getStringValue())));
currentCellData.setStringValue(analysisContext.currentWorkbookHolder().getReadCache()
.get(Integer.valueOf(currentCellData.getStringValue())));
}
curRowContent[curCol] = currentCellData;
}

22
src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java

@ -1,19 +1,20 @@
package com.alibaba.excel.analysis.v07.handlers;
import org.xml.sax.Attributes;
import static com.alibaba.excel.constant.ExcelXmlConstants.ROW_TAG;
import org.xml.sax.Attributes;
import com.alibaba.excel.analysis.v07.XlsxCellHandler;
import com.alibaba.excel.analysis.v07.XlsxRowResultHolder;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.EachRowAnalysisFinishEvent;
public class ProcessResultCellHandler implements XlsxCellHandler {
private AnalysisEventRegistryCenter registerCenter;
private AnalysisContext analysisContext;
private XlsxRowResultHolder rowResultHandler;
public ProcessResultCellHandler(AnalysisEventRegistryCenter registerCenter,
XlsxRowResultHolder rowResultHandler) {
this.registerCenter = registerCenter;
public ProcessResultCellHandler(AnalysisContext analysisContext, XlsxRowResultHolder rowResultHandler) {
this.analysisContext = analysisContext;
this.rowResultHandler = rowResultHandler;
}
@ -23,14 +24,13 @@ public class ProcessResultCellHandler implements XlsxCellHandler {
}
@Override
public void startHandle(String name, Attributes attributes) {
}
public void startHandle(String name, Attributes attributes) {}
@Override
public void endHandle(String name) {
registerCenter.notify(new EachRowAnalysisFinishEvent(rowResultHandler.getCurRowContent(),
rowResultHandler.getColumnSize()));
analysisContext.currentSheetHolder().notifyAll(
new EachRowAnalysisFinishEvent(rowResultHandler.getCurRowContent(), rowResultHandler.getColumnSize()),
analysisContext);
rowResultHandler.clearResult();
}

27
src/main/java/com/alibaba/excel/cache/Cache.java vendored

@ -1,27 +0,0 @@
package com.alibaba.excel.cache;
/**
* cache
*
* @author zhuangjiaju
*/
public interface Cache {
/**
* put
*
* @param key
* @param value
*/
void put(Integer key, String value);
/**
* get
*
* @param key
* @return
*/
String get(Integer key);
void finish();
}

4
src/main/java/com/alibaba/excel/cache/Ehcache.java vendored

@ -24,10 +24,10 @@ import com.alibaba.excel.util.StringUtils;
*
* @author zhuangjiaju
*/
public class Ehcache implements Cache {
public class Ehcache implements ReadCache {
private static final Logger LOGGER = LoggerFactory.getLogger(Ehcache.class);
private static final int BATCH = 500;
// private org.ehcache.Cache<Integer, String> cache;
// private org.ehcache.ReadCache<Integer, String> cache;
int index = 0;
int expirekey = 0;
private Map<Integer, String> cache = new HashMap<Integer, String>();

15
src/main/java/com/alibaba/excel/cache/Ehcache2.java vendored

@ -3,23 +3,16 @@ package com.alibaba.excel.cache;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default cache
*
* Putting temporary data directly into a map is a little more efficient but very memory intensive
*
* @author zhuangjiaju
*/
public class Ehcache2 implements Cache {
private static final Logger LOGGER = LoggerFactory.getLogger(Ehcache2.class);
int index = 0;
// private org.ehcache.Cache<Integer, String> cache;
public class MapCache implements ReadCache {
private Map<Integer, String> cache = new HashMap<Integer, String>();
public Ehcache2() {}
public MapCache() {}
@Override
public void put(Integer key, String value) {

2
src/main/java/com/alibaba/excel/cache/EhcacheFile.java vendored

@ -24,7 +24,7 @@ import com.alibaba.excel.util.StringUtils;
*
* @author zhuangjiaju
*/
public class EhcacheFile implements Cache {
public class EhcacheFile implements ReadCache {
private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheFile.class);
private static final int BATCH = 500;
int index = 0;

2
src/main/java/com/alibaba/excel/cache/EhcacheMix.java vendored

@ -24,7 +24,7 @@ import com.alibaba.excel.util.StringUtils;
*
* @author zhuangjiaju
*/
public class EhcacheMix implements Cache {
public class EhcacheMix implements ReadCache {
private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheMix.class);
private static final int BATCH = 500;
int index = 0;

34
src/main/java/com/alibaba/excel/cache/ReadCache.java vendored

@ -0,0 +1,34 @@
package com.alibaba.excel.cache;
/**
* Read cache
*
* @author zhuangjiaju
*/
public interface ReadCache {
/**
* Automatically generate the key and put it in the cache.Key start from 0
*
* @param value
*/
void put(String value);
/**
* Get
*
* @param key
* @return
*/
String get(Integer key);
/**
* 所有
*/
void putFinished();
/**
*
*/
void destroy();
}

4
src/main/java/com/alibaba/excel/cache/SharedStringsTableCache.java → src/main/java/com/alibaba/excel/cache/SharedStringsTableReadCache.java vendored

@ -7,10 +7,10 @@ import org.apache.poi.xssf.model.SharedStringsTable;
*
* @author zhuangjiaju
*/
public class SharedStringsTableCache implements Cache {
public class SharedStringsTableReadCache implements ReadCache {
private SharedStringsTable sharedStringsTable;
public SharedStringsTableCache(SharedStringsTable sharedStringsTable) {
public SharedStringsTableReadCache(SharedStringsTable sharedStringsTable) {
this.sharedStringsTable = sharedStringsTable;
}

116
src/main/java/com/alibaba/excel/context/AnalysisContext.java

@ -1,77 +1,76 @@
package com.alibaba.excel.context;
import java.io.InputStream;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.event.EachRowAnalysisFinishEvent;
import com.alibaba.excel.metadata.holder.ReadConfiguration;
import com.alibaba.excel.metadata.holder.SheetHolder;
import com.alibaba.excel.metadata.holder.WorkbookHolder;
/**
*
* A context is the main anchorage point of a excel reader.
*
* @author jipengfei
*/
public interface AnalysisContext {
/**
* Custom attribute
* Select the current table
*
* @param sheet
*/
Object getCustom();
void currentSheet(com.alibaba.excel.metadata.Sheet sheet);
/**
* get current sheet
* All information about the workbook you are currently working on
*
* @return current analysis sheet
* @return
*/
Sheet getCurrentSheet();
WorkbookHolder currentWorkbookHolder();
/**
* set current sheet
* @param sheet
* All information about the sheet you are currently working on
*
* @return
*/
void setCurrentSheet(Sheet sheet);
SheetHolder currentSheetHolder();
/**
* Configuration of currently operated cell
*
* get excel type
* @return excel type
* @return
*/
ExcelTypeEnum getExcelType();
ReadConfiguration currentConfiguration();
/**
* get in io
* @return file io
* set current result
*
* @param result
*/
InputStream getInputStream();
void setCurrentRowAnalysisResult(Object result);
/**
*
* custom listener
* @return listener
* get current result
*
* @return get current result
*/
AnalysisEventListener<Object> getEventListener();
Object currentRowAnalysisResult();
/**
* get the converter registry center.
* @return converter registry center.
*/
ConverterRegistryCenter getConverterRegistryCenter();
/**
* get current row
*
* @return
*/
Integer getCurrentRowNum();
Integer currentRowNum();
/**
* set current row num
* set current row num
*
* @param row
*/
void setCurrentRowNum(Integer row);
/**
* get total row ,Data may be inaccurate
* get total row , Data may be inaccurate
*
* @return
*/
@Deprecated
@ -83,53 +82,4 @@ public interface AnalysisContext {
* @param totalCount
*/
void setTotalCount(Integer totalCount);
/**
* get excel head
* @return
*/
ExcelHeadProperty getExcelHeadProperty();
/**
* set the excel head property
* @param excelHeadProperty the excel property to set.
*/
void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty);
/**
*
*if need to short match the content
* @return
*/
boolean trim();
/**
* set current result
* @param result
*/
void setCurrentRowAnalysisResult(Object result);
/**
* get current result
* @return get current result
*/
Object getCurrentRowAnalysisResult();
/**
* Interrupt execution
*/
void interrupt();
/**
* date use1904WindowDate
* @return
*/
boolean use1904WindowDate();
/**
* date use1904WindowDate
* @param use1904WindowDate
*/
void setUse1904WindowDate(boolean use1904WindowDate);
}

193
src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java

@ -1,176 +1,47 @@
package com.alibaba.excel.context;
import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.metadata.holder.SheetHolder;
import com.alibaba.excel.metadata.holder.WorkbookHolder;
/**
*
* @author jipengfei
*/
public class AnalysisContextImpl implements AnalysisContext {
private Object custom;
private Sheet currentSheet;
private ExcelTypeEnum excelType;
private InputStream inputStream;
private AnalysisEventListener<Object> eventListener;
private Integer currentRowNum;
private Integer totalCount;
private ExcelHeadProperty excelHeadProperty;
private boolean trim;
private boolean use1904WindowDate = false;
private ConverterRegistryCenter converterRegistryCenter;
@Override
public void setUse1904WindowDate(boolean use1904WindowDate) {
this.use1904WindowDate = use1904WindowDate;
}
@Override
public Object getCurrentRowAnalysisResult() {
return currentRowAnalysisResult;
}
@Override
public void interrupt() {
throw new ExcelAnalysisException("interrupt error");
}
@Override
public boolean use1904WindowDate() {
return use1904WindowDate;
}
@Override
public void setCurrentRowAnalysisResult(Object currentRowAnalysisResult) {
this.currentRowAnalysisResult = currentRowAnalysisResult;
}
private Object currentRowAnalysisResult;
public AnalysisContextImpl(InputStream inputStream, ExcelTypeEnum excelTypeEnum, Object custom,
AnalysisEventListener<Object> listener, ConverterRegistryCenter converterRegistryCenter, boolean trim) {
this.custom = custom;
this.eventListener = listener;
this.inputStream = inputStream;
this.excelType = excelTypeEnum;
this.trim = trim;
this.converterRegistryCenter = converterRegistryCenter;
}
@Override
public void setCurrentSheet(Sheet currentSheet) {
cleanCurrentSheet();
this.currentSheet = currentSheet;
if (currentSheet.getClazz() != null) {
excelHeadProperty =
ExcelHeadProperty.buildExcelHeadProperty(this.excelHeadProperty, currentSheet.getClazz(), null);
private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisContextImpl.class);
/**
* The Workbook currently written
*/
private WorkbookHolder currentWorkbookHolder;
/**
* Current sheet holder
*/
private SheetHolder currentSheetHolder;
public AnalysisContextImpl(com.alibaba.excel.metadata.Workbook workbook) {
if (workbook == null) {
throw new IllegalArgumentException("Workbook argument cannot be null");
}
currentWorkbookHolder = WorkbookHolder.buildReadWorkbookHolder(workbook);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Initialization 'AnalysisContextImpl' complete");
}
}
private void cleanCurrentSheet() {
this.currentSheet = null;
this.excelHeadProperty = null;
this.totalCount = 0;
this.currentRowAnalysisResult = null;
this.currentRowNum =0;
}
@Override
public ExcelTypeEnum getExcelType() {
return excelType;
}
public void setExcelType(ExcelTypeEnum excelType) {
this.excelType = excelType;
}
public Object getCustom() {
return custom;
}
public void setCustom(Object custom) {
this.custom = custom;
}
@Override
public Sheet getCurrentSheet() {
return currentSheet;
}
@Override
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public AnalysisEventListener<Object> getEventListener() {
return eventListener;
}
public void setEventListener(AnalysisEventListener<Object> eventListener) {
this.eventListener = eventListener;
}
@Override
public Integer getCurrentRowNum() {
return this.currentRowNum;
}
@Override
public void setCurrentRowNum(Integer row) {
this.currentRowNum = row;
}
@Override
public Integer getTotalCount() {
return totalCount;
}
@Override
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
}
@Override
public ExcelHeadProperty getExcelHeadProperty() {
return this.excelHeadProperty;
}
@Override
public void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty) {
this.excelHeadProperty = excelHeadProperty;
}
@Override
public boolean trim() {
return this.trim;
}
@Override
public ConverterRegistryCenter getConverterRegistryCenter() {
return converterRegistryCenter;
public void currentSheet(com.alibaba.excel.metadata.Sheet sheet) {
if (sheet == null) {
throw new IllegalArgumentException("Sheet argument cannot be null");
}
if (sheet.getSheetNo() == null || sheet.getSheetNo() <= 0) {
sheet.setSheetNo(0);
}
currentSheetHolder = SheetHolder.buildReadWorkSheetHolder(sheet, currentWorkbookHolder);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Began to read:{}", sheet);
}
}
}

4
src/main/java/com/alibaba/excel/context/WriteContext.java

@ -1,7 +1,7 @@
package com.alibaba.excel.context;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.metadata.holder.ConfigurationSelector;
import com.alibaba.excel.metadata.holder.WriteConfiguration;
import com.alibaba.excel.metadata.holder.SheetHolder;
import com.alibaba.excel.metadata.holder.TableHolder;
import com.alibaba.excel.metadata.holder.WorkbookHolder;
@ -31,7 +31,7 @@ public interface WriteContext {
*
* @return
*/
ConfigurationSelector currentConfigurationSelector();
WriteConfiguration currentConfiguration();
/**
* All information about the workbook you are currently working on

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

@ -14,10 +14,10 @@ import org.slf4j.LoggerFactory;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.metadata.holder.ConfigurationSelector;
import com.alibaba.excel.metadata.holder.SheetHolder;
import com.alibaba.excel.metadata.holder.TableHolder;
import com.alibaba.excel.metadata.holder.WorkbookHolder;
import com.alibaba.excel.metadata.holder.WriteConfiguration;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import com.alibaba.excel.util.WorkBookUtil;
import com.alibaba.excel.write.handler.CellWriteHandler;
@ -50,7 +50,7 @@ public class WriteContextImpl implements WriteContext {
/**
* Configuration of currently operated cell
*/
private ConfigurationSelector currentConfigurationSelector;
private WriteConfiguration currentWriteConfiguration;
public WriteContextImpl(com.alibaba.excel.metadata.Workbook workbook) {
if (workbook == null) {
@ -62,8 +62,8 @@ public class WriteContextImpl implements WriteContext {
initCurrentWorkbookHolder(workbook);
beforeWorkbookCreate();
try {
currentWorkbookHolder.setWorkbook(WorkBookUtil.createWorkBook(workbook));
} catch (IOException e) {
currentWorkbookHolder.setWorkbook(WorkBookUtil.createWorkBook(currentWorkbookHolder));
} catch (Exception e) {
throw new ExcelGenerateException("Create workbook failure", e);
}
afterWorkbookCreate();
@ -73,7 +73,7 @@ public class WriteContextImpl implements WriteContext {
}
private void beforeWorkbookCreate() {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(WorkbookWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -85,7 +85,7 @@ public class WriteContextImpl implements WriteContext {
}
private void afterWorkbookCreate() {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(WorkbookWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(WorkbookWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -98,9 +98,9 @@ public class WriteContextImpl implements WriteContext {
private void initCurrentWorkbookHolder(com.alibaba.excel.metadata.Workbook workbook) {
currentWorkbookHolder = new WorkbookHolder(workbook);
currentConfigurationSelector = currentWorkbookHolder;
currentWriteConfiguration = currentWorkbookHolder;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("CurrentConfigurationSelector is currentWorkbookHolder");
LOGGER.debug("CurrentConfiguration is currentWorkbookHolder");
}
}
@ -122,9 +122,9 @@ public class WriteContextImpl implements WriteContext {
currentSheetHolder = currentWorkbookHolder.getHasBeenInitializedSheet().get(sheet.getSheetNo());
currentSheetHolder.setNewInitialization(Boolean.FALSE);
currentTableHolder = null;
currentConfigurationSelector = currentSheetHolder;
currentWriteConfiguration = currentSheetHolder;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("CurrentConfigurationSelector is currentSheetHolder");
LOGGER.debug("CurrentConfiguration is currentSheetHolder");
}
return;
}
@ -136,7 +136,7 @@ public class WriteContextImpl implements WriteContext {
}
private void beforeSheetCreate() {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(SheetWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -148,7 +148,7 @@ public class WriteContextImpl implements WriteContext {
}
private void afterSheetCreate() {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(SheetWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(SheetWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -167,9 +167,9 @@ public class WriteContextImpl implements WriteContext {
currentSheetHolder = new SheetHolder(sheet, currentWorkbookHolder);
currentWorkbookHolder.getHasBeenInitializedSheet().put(sheet.getSheetNo(), currentSheetHolder);
currentTableHolder = null;
currentConfigurationSelector = currentSheetHolder;
currentWriteConfiguration = currentSheetHolder;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("CurrentConfigurationSelector is currentSheetHolder");
LOGGER.debug("CurrentConfiguration is currentSheetHolder");
}
}
@ -179,7 +179,7 @@ public class WriteContextImpl implements WriteContext {
currentSheet = currentWorkbookHolder.getWorkbook().getSheetAt(sheet.getSheetNo());
} catch (Exception e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.info("Can not find sheet:{} ,now create it", sheet.getSheetNo());
LOGGER.debug("Can not find sheet:{} ,now create it", sheet.getSheetNo());
}
currentSheet = WorkBookUtil.createSheet(currentWorkbookHolder.getWorkbook(), sheet);
}
@ -189,11 +189,11 @@ public class WriteContextImpl implements WriteContext {
}
public void initHead(ExcelHeadProperty excelHeadProperty) {
if (!currentConfigurationSelector.needHead() || !currentSheetHolder.getExcelHeadProperty().hasHead()) {
if (!currentWriteConfiguration.needHead() || !currentSheetHolder.getExcelHeadProperty().hasHead()) {
return;
}
int lastRowNum = currentSheetHolder.getSheet().getLastRowNum();
int rowIndex = lastRowNum + currentConfigurationSelector.writeRelativeHeadRowIndex();
int rowIndex = lastRowNum + currentWriteConfiguration.writeRelativeHeadRowIndex();
// Combined head
addMergedRegionToCurrentSheet(excelHeadProperty, rowIndex);
for (int relativeRowIndex = 0, i = rowIndex; i < excelHeadProperty.getHeadRowNumber() + rowIndex;
@ -206,7 +206,7 @@ public class WriteContextImpl implements WriteContext {
}
private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(RowWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -219,7 +219,7 @@ public class WriteContextImpl implements WriteContext {
}
private void afterRowCreate(Row row, int relativeRowIndex) {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(RowWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -251,7 +251,7 @@ public class WriteContextImpl implements WriteContext {
}
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(CellWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -264,7 +264,7 @@ public class WriteContextImpl implements WriteContext {
}
private void afterCellCreate(Head head, Cell cell, int relativeRowIndex) {
List<WriteHandler> handlerList = currentConfigurationSelector.writeHandlerMap().get(CellWriteHandler.class);
List<WriteHandler> handlerList = currentWriteConfiguration.writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -293,9 +293,9 @@ public class WriteContextImpl implements WriteContext {
}
currentTableHolder = currentSheetHolder.getHasBeenInitializedTable().get(table.getTableNo());
currentTableHolder.setNewInitialization(Boolean.FALSE);
currentConfigurationSelector = currentTableHolder;
currentWriteConfiguration = currentTableHolder;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("CurrentConfigurationSelector is currentTableHolder");
LOGGER.debug("CurrentConfiguration is currentTableHolder");
}
return;
}
@ -306,15 +306,15 @@ public class WriteContextImpl implements WriteContext {
private void initCurrentTableHolder(com.alibaba.excel.metadata.Table table) {
currentTableHolder = new TableHolder(table, currentSheetHolder, currentWorkbookHolder);
currentSheetHolder.getHasBeenInitializedTable().put(table.getTableNo(), currentTableHolder);
currentConfigurationSelector = currentTableHolder;
currentWriteConfiguration = currentTableHolder;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("CurrentConfigurationSelector is currentTableHolder");
LOGGER.debug("CurrentConfiguration is currentTableHolder");
}
}
@Override
public ConfigurationSelector currentConfigurationSelector() {
return currentConfigurationSelector;
public WriteConfiguration currentConfiguration() {
return currentWriteConfiguration;
}
@Override

9
src/main/java/com/alibaba/excel/converters/ConverterRegistryCenter.java

@ -1,9 +0,0 @@
package com.alibaba.excel.converters;
import java.util.Collection;
import java.util.Map;
public interface ConverterRegistryCenter {
void register(Converter converter);
Map<ConverterKey, Converter> getConverters();
}

8
src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java

@ -28,8 +28,12 @@ public class DateNumberConverter implements Converter<Date> {
@Override
public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty) {
if (contentProperty.getDateTimeFormatProperty() == null) {
return HSSFDateUtil.getJavaDate(cellData.getDoubleValue(), false, null);
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
Boolean use1904windowing = Boolean.FALSE;
if (contentProperty != null && contentProperty.getUse1904windowing() != null) {
use1904windowing = contentProperty.getUse1904windowing();
}
return HSSFDateUtil.getJavaDate(cellData.getDoubleValue(), use1904windowing, null);
} else {
return HSSFDateUtil.getJavaDate(cellData.getDoubleValue(),
contentProperty.getDateTimeFormatProperty().getUse1904windowing(), null);

4
src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java

@ -27,7 +27,7 @@ public class DateStringConverter implements Converter<Date> {
@Override
public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty) throws ParseException {
if (contentProperty.getDateTimeFormatProperty() == null) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return DateUtils.parseDate(cellData.getStringValue(), null);
} else {
return DateUtils.parseDate(cellData.getStringValue(),
@ -37,7 +37,7 @@ public class DateStringConverter implements Converter<Date> {
@Override
public CellData convertToExcelData(Date value, ExcelContentProperty contentProperty) {
if (contentProperty.getDateTimeFormatProperty() == null) {
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
return new CellData(DateUtils.format(value, null));
} else {
return new CellData(DateUtils.format(value, contentProperty.getDateTimeFormatProperty().getFormat()));

2
src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java

@ -29,7 +29,7 @@ public class StringNumberConverter implements Converter<String> {
@Override
public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty) {
// If there are "DateTimeFormat", read as date
if (contentProperty.getDateTimeFormatProperty() != null) {
if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {
return DateUtils.format(
HSSFDateUtil.getJavaDate(cellData.getDoubleValue(),
contentProperty.getDateTimeFormatProperty().getUse1904windowing(), null),

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

@ -1,6 +1,7 @@
package com.alibaba.excel.event;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
/**
* Receives the return of each piece of data parsed
@ -21,12 +22,7 @@ public abstract class AnalysisEventListener<T> implements ReadListener<T> {
throw exception;
}
/**
* Verify that there is another piece of data.You can stop the read by returning false
*
* @param context
* @return
*/
@Override
public boolean hasNext(AnalysisContext context) {
return true;
}

35
src/main/java/com/alibaba/excel/event/AnalysisEventRegistryCenter.java

@ -1,35 +0,0 @@
package com.alibaba.excel.event;
/**
* Event center.
*
* @author jipengfei
*/
public interface AnalysisEventRegistryCenter {
/**
* Append listener
*
* @param name listener name.
* @param listener Callback method after each row is parsed.
*/
void register(String name, AnalysisEventListener<Object> listener);
/**
* Parse one row to notify all event listeners
*
* @param event parse event
*/
void notify(AnalysisFinishEvent event);
/**
* Clean all listeners.
*/
void cleanAllListeners();
/**
* clean listener by name
* @param name the listener name
*/
void cleanListener(String name);
}

1
src/main/java/com/alibaba/excel/event/EachRowAnalysisFinishEvent.java

@ -10,6 +10,7 @@ import com.alibaba.excel.metadata.CellData;
*/
public class EachRowAnalysisFinishEvent implements AnalysisFinishEvent {
private Object result;
public EachRowAnalysisFinishEvent(Object content) {
this.result = content;
}

81
src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java

@ -1,81 +0,0 @@
package com.alibaba.excel.event;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import net.sf.cglib.beans.BeanMap;
/**
* @author jipengfei
*/
public class ModelBuildEventListener extends AnalysisEventListener<Object> {
private final Map<ConverterKey, Converter> converters;
public ModelBuildEventListener(Map<ConverterKey, Converter> converters) {
this.converters = converters;
}
@Override
public void invoke(Object object, AnalysisContext context) {
if (context.getExcelHeadProperty() != null && context.getExcelHeadProperty().getHeadClazz() != null) {
try {
@SuppressWarnings("unchecked")
Object resultModel = buildUserModel(context, (List<CellData>)object);
context.setCurrentRowAnalysisResult(resultModel);
} catch (Exception e) {
throw new ExcelGenerateException(e);
}
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private Object buildUserModel(AnalysisContext context, List<CellData> cellDataList) throws Exception {
ExcelHeadProperty excelHeadProperty = context.getExcelHeadProperty();
Object resultModel = excelHeadProperty.getHeadClazz().newInstance();
Map<String,Object> map = new HashMap<String,Object>();
for (int i = 0; i < cellDataList.size(); i++) {
ExcelContentProperty contentProperty = excelHeadProperty.getContentPropertyMap().get(i);
if (contentProperty != null) {
CellData cellData = cellDataList.get(i);
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
continue;
}
Object value = convertValue(cellDataList.get(i), contentProperty.getField().getClass(), contentProperty);
if (value != null) {
map.put(contentProperty.getField().getName(), value);
}
}
}
BeanMap.create(resultModel).putAll(map);
return resultModel;
}
private Object convertValue(CellData cellData, Class clazz, ExcelContentProperty contentProperty) {
Converter converter = converters.get(ConverterKey.buildConverterKey(clazz, cellData.getType()));
if (converter == null) {
throw new ExcelDataConvertException(
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
}
try {
return converter.convertToJavaData(cellData, contentProperty);
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to " + clazz + " error ", e);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
}

26
src/main/java/com/alibaba/excel/metadata/BasicParameter.java

@ -1,12 +1,10 @@
package com.alibaba.excel.metadata;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.event.ReadListener;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.write.handler.WriteHandler;
/**
@ -42,7 +40,7 @@ public class BasicParameter {
/**
* Custom type conversions override the default
*/
private Map<Class, Converter> customConverterMap = new HashMap<Class, Converter>();
private List<Converter> customConverterList = new ArrayList<Converter>();
/**
* Custom type handler override the default
*/
@ -51,6 +49,10 @@ public class BasicParameter {
* Custom type listener run after default
*/
private List<ReadListener> customReadListenerList = new ArrayList<ReadListener>();
/**
* Automatic trim includes sheet name and content
*/
private Boolean autoTrim;
public Integer getReadHeadRowNumber() {
return readHeadRowNumber;
@ -92,12 +94,12 @@ public class BasicParameter {
this.needHead = needHead;
}
public Map<Class, Converter> getCustomConverterMap() {
return customConverterMap;
public List<Converter> getCustomConverterList() {
return customConverterList;
}
public void setCustomConverterMap(Map<Class, Converter> customConverterMap) {
this.customConverterMap = customConverterMap;
public void setCustomConverterList(List<Converter> customConverterList) {
this.customConverterList = customConverterList;
}
public List<WriteHandler> getCustomWriteHandlerList() {
@ -115,4 +117,12 @@ public class BasicParameter {
public void setCustomReadListenerList(List<ReadListener> customReadListenerList) {
this.customReadListenerList = customReadListenerList;
}
public Boolean getAutoTrim() {
return autoTrim;
}
public void setAutoTrim(Boolean autoTrim) {
this.autoTrim = autoTrim;
}
}

13
src/main/java/com/alibaba/excel/metadata/Head.java

@ -24,7 +24,10 @@ public class Head {
* Head name
*/
private List<String> headNameList;
/**
* Whether index is specified
*/
private Boolean forceIndex;
/**
* Cell style property
*/
@ -89,4 +92,12 @@ public class Head {
public void setColumnWidthProperty(ColumnWidthProperty columnWidthProperty) {
this.columnWidthProperty = columnWidthProperty;
}
public Boolean getForceIndex() {
return forceIndex;
}
public void setForceIndex(Boolean forceIndex) {
this.forceIndex = forceIndex;
}
}

43
src/main/java/com/alibaba/excel/metadata/Workbook.java

@ -4,6 +4,9 @@ import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.handler.WriteHandler;
@ -41,6 +44,22 @@ public class Workbook extends BasicParameter {
* Default true
*/
private Boolean autoCloseStream;
/**
* This object can be read in the Listener {@link AnalysisEventListener#invoke(Object, AnalysisContext)}
* {@link AnalysisContext#getCustom()}
*
*/
private Object readCustomObject;
/**
* A cache that stores temp data to save memory.Default use {@link com.alibaba.excel.cache.Ehcache}
*/
private ReadCache readCache;
/**
* true if date uses 1904 windowing, or false if using 1900 date windowing.
*
* @return
*/
private Boolean use1904windowing;
/**
* 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.
@ -112,4 +131,28 @@ public class Workbook extends BasicParameter {
public void setConvertAllFiled(Boolean convertAllFiled) {
this.convertAllFiled = convertAllFiled;
}
public Object getReadCustomObject() {
return readCustomObject;
}
public void setReadCustomObject(Object readCustomObject) {
this.readCustomObject = readCustomObject;
}
public ReadCache getReadCache() {
return readCache;
}
public void setReadCache(ReadCache readCache) {
this.readCache = readCache;
}
public Boolean getUse1904windowing() {
return use1904windowing;
}
public void setUse1904windowing(Boolean use1904windowing) {
this.use1904windowing = use1904windowing;
}
}

204
src/main/java/com/alibaba/excel/metadata/holder/AbstractConfigurationSelector.java → src/main/java/com/alibaba/excel/metadata/holder/AbstractWriteConfiguration.java

@ -11,16 +11,26 @@ import java.util.TreeMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.AnalysisFinishEvent;
import com.alibaba.excel.event.NotRepeatExecutor;
import com.alibaba.excel.event.Order;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.CellStyle;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.property.CellStyleProperty;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import com.alibaba.excel.metadata.property.RowHeightProperty;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.read.listener.ReadListenerRegistryCenter;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
@ -35,7 +45,8 @@ import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
*
* @author zhuangjiaju
*/
public abstract class AbstractConfigurationSelector implements ConfigurationSelector {
public abstract class AbstractWriteConfiguration
implements WriteConfiguration, ReadConfiguration, ReadListenerRegistryCenter {
/**
* Need Head
*/
@ -44,10 +55,18 @@ public abstract class AbstractConfigurationSelector implements ConfigurationSele
* Write handler for workbook
*/
private Map<Class<? extends WriteHandler>, List<WriteHandler>> writeHandlerMap;
/**
* Read listener
*/
private List<ReadListener> readListenerList;
/**
* Converter for workbook
*/
private Map<ConverterKey, Converter> readConverterMap;
/**
* Converter for workbook
*/
private Map<Class, Converter> converterMap;
private Map<Class, Converter> writeConverterMap;
/**
* Excel head property
*/
@ -60,17 +79,28 @@ public abstract class AbstractConfigurationSelector implements ConfigurationSele
* Record whether it's new or from cache
*/
private Boolean newInitialization;
/**
* You can only choose one of the {@link AbstractConfigurationSelector#head} and
* {@link AbstractConfigurationSelector#clazz}
* Count the number of added heads when read sheet.
*
* <li>0 - This Sheet has no head ,since the first row are the data
* <li>1 - This Sheet has one row head , this is the default
* <li>2 - This Sheet has two row head ,since the third row is the data
*/
private Integer readHeadRowNumber;
/**
* You can only choose one of the {@link AbstractWriteConfiguration#head} and
* {@link AbstractWriteConfiguration#clazz}
*/
private List<List<String>> head;
/**
* You can only choose one of the {@link AbstractConfigurationSelector#head} and
* {@link AbstractConfigurationSelector#clazz}
* You can only choose one of the {@link AbstractWriteConfiguration#head} and
* {@link AbstractWriteConfiguration#clazz}
*/
private Class clazz;
/**
* Automatic trim includes sheet name and content
*/
private Boolean autoTrim;
public Boolean getNeedHead() {
return needHead;
@ -88,14 +118,6 @@ public abstract class AbstractConfigurationSelector implements ConfigurationSele
this.writeHandlerMap = writeHandlerMap;
}
public Map<Class, Converter> getConverterMap() {
return converterMap;
}
public void setConverterMap(Map<Class, Converter> converterMap) {
this.converterMap = converterMap;
}
public ExcelHeadProperty getExcelHeadProperty() {
return excelHeadProperty;
}
@ -136,6 +158,139 @@ public abstract class AbstractConfigurationSelector implements ConfigurationSele
this.clazz = clazz;
}
public Boolean getAutoTrim() {
return autoTrim;
}
public void setAutoTrim(Boolean autoTrim) {
this.autoTrim = autoTrim;
}
public List<ReadListener> getReadListenerList() {
return readListenerList;
}
public void setReadListenerList(List<ReadListener> readListenerList) {
this.readListenerList = readListenerList;
}
public Map<ConverterKey, Converter> getReadConverterMap() {
return readConverterMap;
}
public void setReadConverterMap(Map<ConverterKey, Converter> readConverterMap) {
this.readConverterMap = readConverterMap;
}
public Map<Class, Converter> getWriteConverterMap() {
return writeConverterMap;
}
public void setWriteConverterMap(Map<Class, Converter> writeConverterMap) {
this.writeConverterMap = writeConverterMap;
}
public Integer getReadHeadRowNumber() {
return readHeadRowNumber;
}
public void setReadHeadRowNumber(Integer readHeadRowNumber) {
this.readHeadRowNumber = readHeadRowNumber;
}
@Override
public void register(AnalysisEventListener listener) {
readListenerList.add(listener);
}
@Override
public void notifyEndOneRow(AnalysisFinishEvent event, AnalysisContext analysisContext) {
List<CellData> cellDataList = (List<CellData>)event.getAnalysisResult();
if (analysisContext.currentRowNum() > analysisContext.currentSheetHolder().getReadHeadRowNumber()) {
for (ReadListener readListener : readListenerList) {
try {
readListener.invoke(analysisContext.currentRowAnalysisResult(), analysisContext);
} catch (Exception e) {
for (ReadListener readListenerException : readListenerList) {
try {
readListenerException.onException(e, analysisContext);
} catch (Exception exception) {
throw new ExcelAnalysisException("Listen error!", exception);
}
}
}
}
}
// Now is header
if (analysisContext.currentRowNum().equals(analysisContext.currentSheetHolder().getReadHeadRowNumber())) {
buildHead(analysisContext, cellDataList);
}
}
@Override
public void notifyAfterAllAnalysed(AnalysisContext analysisContext) {
for (ReadListener readListener : readListenerList) {
readListener.doAfterAllAnalysed(analysisContext);
}
}
private void buildHead(AnalysisContext analysisContext, List<CellData> cellDataList) {
if (!HeadKindEnum.CLASS.equals(analysisContext.currentConfiguration().excelHeadProperty().getHeadKind())) {
return;
}
List<String> dataList = (List<String>)buildStringList(cellDataList, analysisContext.currentConfiguration());
ExcelHeadProperty excelHeadPropertyData = analysisContext.currentConfiguration().excelHeadProperty();
Map<Integer, Head> headMapData = excelHeadPropertyData.getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMapData = excelHeadPropertyData.getContentPropertyMap();
Map<Integer, Head> tmpHeadMap = new HashMap<Integer, Head>(headMapData.size() * 4 / 3 + 1);
Map<Integer, ExcelContentProperty> tmpContentPropertyMap =
new HashMap<Integer, ExcelContentProperty>(contentPropertyMapData.size() * 4 / 3 + 1);
for (Map.Entry<Integer, Head> entry : headMapData.entrySet()) {
Head headData = entry.getValue();
if (headData.getForceIndex()) {
tmpHeadMap.put(entry.getKey(), headData);
tmpContentPropertyMap.put(entry.getKey(), contentPropertyMapData.get(entry.getKey()));
continue;
}
String headName = headData.getHeadNameList().get(0);
for (int i = 0; i < dataList.size(); i++) {
String headString = dataList.get(i);
if (StringUtils.isEmpty(headString)) {
continue;
}
if (analysisContext.currentSheetHolder().getAutoTrim()) {
headString = headString.trim();
}
if (headName.equals(headString)) {
headData.setColumnIndex(i);
tmpHeadMap.put(i, headData);
tmpContentPropertyMap.put(i, contentPropertyMapData.get(entry.getKey()));
break;
}
}
}
excelHeadPropertyData.setHeadMap(tmpHeadMap);
excelHeadPropertyData.setContentPropertyMap(tmpContentPropertyMap);
}
private Object buildStringList(List<CellData> data, ReadConfiguration readConfiguration) {
List<String> list = new ArrayList<String>();
for (CellData cellData : data) {
Converter converter = readConfiguration.readConverterMap()
.get(ConverterKey.buildConverterKey(String.class, cellData.getType()));
if (converter == null) {
throw new ExcelDataConvertException(
"Converter not found, convert " + cellData.getType() + " to String");
}
try {
list.add((String)(converter.convertToJavaData(cellData, null)));
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to String error ", e);
}
}
return list;
}
protected Map<Class<? extends WriteHandler>, List<WriteHandler>> sortAndClearUpHandler(
List<WriteHandler> handlerList, Map<Class<? extends WriteHandler>, List<WriteHandler>> parentHandlerMap) {
// add
@ -301,11 +456,6 @@ public abstract class AbstractConfigurationSelector implements ConfigurationSele
return getWriteHandlerMap();
}
@Override
public Map<Class, Converter> converterMap() {
return getConverterMap();
}
@Override
public boolean needHead() {
return getNeedHead();
@ -326,4 +476,18 @@ public abstract class AbstractConfigurationSelector implements ConfigurationSele
return getNewInitialization();
}
@Override
public List<ReadListener> readListenerList() {
return getReadListenerList();
}
@Override
public Map<ConverterKey, Converter> readConverterMap() {
return getReadConverterMap();
}
@Override
public Map<Class, Converter> writeConverterMap() {
return getWriteConverterMap();
}
}

39
src/main/java/com/alibaba/excel/metadata/holder/ReadConfiguration.java

@ -0,0 +1,39 @@
package com.alibaba.excel.metadata.holder;
import java.util.List;
import java.util.Map;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import com.alibaba.excel.read.listener.ReadListener;
/**
*
* Get the corresponding configuration
*
* @author zhuangjiaju
**/
public interface ReadConfiguration {
/**
* What handler does the currently operated cell need to execute
*
* @return
*/
List<ReadListener> readListenerList();
/**
* What converter does the currently operated cell need to execute
*
* @return
*/
Map<ConverterKey, Converter> readConverterMap();
/**
* What 'ExcelHeadProperty' does the currently operated cell need to execute
*
* @return
*/
ExcelHeadProperty excelHeadProperty();
}

114
src/main/java/com/alibaba/excel/metadata/holder/SheetHolder.java

@ -10,10 +10,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.metadata.CellStyle;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.TableStyle;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.style.RowCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractHeadColumnWidthStyleStrategy;
@ -23,9 +25,8 @@ import com.alibaba.excel.write.style.column.AbstractHeadColumnWidthStyleStrategy
*
* @author zhuangjiaju
*/
public class SheetHolder extends AbstractConfigurationSelector {
public class SheetHolder extends AbstractWriteConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(SheetHolder.class);
/***
* poi sheet
*/
@ -51,32 +52,20 @@ public class SheetHolder extends AbstractConfigurationSelector {
*/
private com.alibaba.excel.metadata.Sheet sheetParam;
public SheetHolder(com.alibaba.excel.metadata.Sheet sheet, WorkbookHolder workbookHolder) {
super();
this.sheetParam = sheet;
this.parentWorkBook = workbookHolder;
boolean noHead = (sheet.getHead() == null || sheet.getHead().isEmpty()) && sheet.getClazz() == null;
if (noHead) {
// Use parent
setHead(workbookHolder.getHead());
setClazz(workbookHolder.getClazz());
} else {
setHead(sheet.getHead());
setClazz(sheet.getClazz());
}
// Initialization property
setExcelHeadProperty(new ExcelHeadProperty(getClazz(), getHead(), workbookHolder.getConvertAllFiled()));
public static SheetHolder buildWriteWorkSheetHolder(com.alibaba.excel.metadata.Sheet sheet,
WorkbookHolder workbookHolder) {
SheetHolder sheetHolder = buildBaseSheetHolder(sheet, workbookHolder);
setNewInitialization(Boolean.TRUE);
sheetHolder.setNewInitialization(Boolean.TRUE);
if (sheet.getNeedHead() == null) {
setNeedHead(workbookHolder.needHead());
sheetHolder.setNeedHead(workbookHolder.needHead());
} else {
setNeedHead(sheet.getNeedHead());
sheetHolder.setNeedHead(sheet.getNeedHead());
}
if (sheet.getWriteRelativeHeadRowIndex() == null) {
setWriteRelativeHeadRowIndex(workbookHolder.writeRelativeHeadRowIndex());
sheetHolder.setWriteRelativeHeadRowIndex(workbookHolder.writeRelativeHeadRowIndex());
} else {
setWriteRelativeHeadRowIndex(sheet.getWriteRelativeHeadRowIndex());
sheetHolder.setWriteRelativeHeadRowIndex(sheet.getWriteRelativeHeadRowIndex());
}
// Compatible with old code
compatibleOldCode(sheet);
@ -85,25 +74,86 @@ public class SheetHolder extends AbstractConfigurationSelector {
handlerList.addAll(sheet.getCustomWriteHandlerList());
}
// Initialization Annotation
initAnnotationConfig(handlerList);
setWriteHandlerMap(sortAndClearUpHandler(handlerList, workbookHolder.getWriteHandlerMap()));
Map<Class, Converter> converterMap = new HashMap<Class, Converter>(workbookHolder.converterMap());
if (sheet.getCustomConverterMap() != null && !sheet.getCustomConverterMap().isEmpty()) {
converterMap.putAll(sheet.getCustomConverterMap());
sheetHolder.initAnnotationConfig(handlerList);
sheetHolder
.setWriteHandlerMap(sheetHolder.sortAndClearUpHandler(handlerList, workbookHolder.getWriteHandlerMap()));
Map<Class, Converter> converterMap = new HashMap<Class, Converter>(workbookHolder.getWriteConverterMap());
if (sheet.getCustomConverterList() != null && !sheet.getCustomConverterList().isEmpty()) {
for (Converter converter : sheet.getCustomConverterList()) {
converterMap.put(converter.getClass(), converter);
}
}
setConverterMap(converterMap);
setHasBeenInitializedTable(new HashMap<Integer, TableHolder>());
sheetHolder.setWriteConverterMap(converterMap);
sheetHolder.setHasBeenInitializedTable(new HashMap<Integer, TableHolder>());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Sheet writeHandlerMap:{}", getWriteHandlerMap());
LOGGER.debug("Sheet writeHandlerMap:{}", sheetHolder.getWriteHandlerMap());
}
return sheetHolder;
}
public static SheetHolder buildReadWorkSheetHolder(com.alibaba.excel.metadata.Sheet sheet,
WorkbookHolder workbookHolder) {
SheetHolder sheetHolder = buildBaseSheetHolder(sheet, workbookHolder);
if (sheet.getReadHeadRowNumber() == null) {
if (workbookHolder.getReadHeadRowNumber() == null) {
sheetHolder.setReadHeadRowNumber(sheetHolder.getExcelHeadProperty().getHeadRowNumber());
} else {
sheetHolder.setReadHeadRowNumber(workbookHolder.getReadHeadRowNumber());
}
} else {
sheetHolder.setReadHeadRowNumber(sheet.getReadHeadRowNumber());
}
Map<ConverterKey, Converter> converterMap =
new HashMap<ConverterKey, Converter>(workbookHolder.getReadConverterMap());
if (sheet.getCustomConverterList() != null && !sheet.getCustomConverterList().isEmpty()) {
for (Converter converter : sheet.getCustomConverterList()) {
converterMap.put(ConverterKey.buildConverterKey(converter), converter);
}
}
sheetHolder.setReadConverterMap(converterMap);
List<ReadListener> readListenerList = new ArrayList<ReadListener>();
if (sheet.getCustomReadListenerList() != null && !sheet.getCustomReadListenerList().isEmpty()) {
readListenerList.addAll(sheet.getCustomReadListenerList());
}
sheetHolder.setReadListenerList(readListenerList);
return sheetHolder;
}
private static SheetHolder buildBaseSheetHolder(com.alibaba.excel.metadata.Sheet sheet,
WorkbookHolder workbookHolder) {
SheetHolder sheetHolder = new SheetHolder();
sheetHolder.setSheetParam(sheet);
sheetHolder.setParentWorkBook(workbookHolder);
boolean noHead = (sheet.getHead() == null || sheet.getHead().isEmpty()) && sheet.getClazz() == null;
if (noHead) {
// Use parent
sheetHolder.setHead(workbookHolder.getHead());
sheetHolder.setClazz(workbookHolder.getClazz());
} else {
sheetHolder.setHead(sheet.getHead());
sheetHolder.setClazz(sheet.getClazz());
}
if (sheet.getAutoTrim() == null) {
workbookHolder.setAutoTrim(workbookHolder.getAutoTrim());
} else {
workbookHolder.setAutoTrim(sheet.getNeedHead());
}
// Initialization property
sheetHolder
.setExcelHeadProperty(new ExcelHeadProperty(sheetHolder.getClazz(), sheetHolder.getHead(), workbookHolder));
return sheetHolder;
}
/**
* Compatible with old code
*/
@Deprecated
private void compatibleOldCode(com.alibaba.excel.metadata.Sheet sheet) {
private static void compatibleOldCode(com.alibaba.excel.metadata.Sheet sheet) {
if (sheet.getColumnWidthMap() != null && !sheet.getColumnWidthMap().isEmpty()) {
final Map<Integer, Integer> columnWidthMap = sheet.getColumnWidthMap();
if (sheet.getCustomWriteHandlerList() == null) {

54
src/main/java/com/alibaba/excel/metadata/holder/TableHolder.java

@ -21,7 +21,7 @@ import com.alibaba.excel.write.style.RowCellStyleStrategy;
*
* @author zhuangjiaju
*/
public class TableHolder extends AbstractConfigurationSelector {
public class TableHolder extends AbstractWriteConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(TableHolder.class);
/***
@ -37,33 +37,35 @@ public class TableHolder extends AbstractConfigurationSelector {
*/
private com.alibaba.excel.metadata.Table tableParam;
public TableHolder(com.alibaba.excel.metadata.Table table, SheetHolder sheetHolder, WorkbookHolder workbookHolder) {
super();
this.tableParam = table;
this.parentSheet = sheetHolder;
this.tableNo = table.getTableNo();
public static TableHolder buildWriteWorkTableHolder(com.alibaba.excel.metadata.Table table, SheetHolder sheetHolder,
WorkbookHolder workbookHolder) {
TableHolder tableHolder = new TableHolder();
tableHolder.setTableParam(table);
tableHolder.setParentSheet(sheetHolder);
tableHolder.setTableNo(table.getTableNo());
boolean noHead = (table.getHead() == null || table.getHead().isEmpty()) && table.getClazz() == null;
if (noHead) {
// Use parent
setHead(sheetHolder.getHead());
setClazz(sheetHolder.getClazz());
tableHolder.setHead(sheetHolder.getHead());
tableHolder.setClazz(sheetHolder.getClazz());
} else {
setHead(table.getHead());
setClazz(table.getClazz());
tableHolder.setHead(table.getHead());
tableHolder.setClazz(table.getClazz());
}
setNewInitialization(Boolean.TRUE);
tableHolder.setNewInitialization(Boolean.TRUE);
// Initialization property
setExcelHeadProperty(new ExcelHeadProperty(getClazz(), getHead(), workbookHolder.getConvertAllFiled()));
tableHolder.setExcelHeadProperty(
new ExcelHeadProperty(tableHolder.getClazz(), tableHolder.getHead(), workbookHolder.getConvertAllFiled()));
if (table.getNeedHead() == null) {
setNeedHead(sheetHolder.needHead());
tableHolder.setNeedHead(sheetHolder.needHead());
} else {
setNeedHead(table.getNeedHead());
tableHolder.setNeedHead(table.getNeedHead());
}
if (table.getWriteRelativeHeadRowIndex() == null) {
setWriteRelativeHeadRowIndex(sheetHolder.writeRelativeHeadRowIndex());
tableHolder.setWriteRelativeHeadRowIndex(sheetHolder.writeRelativeHeadRowIndex());
} else {
setWriteRelativeHeadRowIndex(table.getWriteRelativeHeadRowIndex());
tableHolder.setWriteRelativeHeadRowIndex(table.getWriteRelativeHeadRowIndex());
}
// Compatible with old code
compatibleOldCode(table);
@ -72,24 +74,28 @@ public class TableHolder extends AbstractConfigurationSelector {
handlerList.addAll(table.getCustomWriteHandlerList());
}
// Initialization Annotation
initAnnotationConfig(handlerList);
tableHolder.initAnnotationConfig(handlerList);
setWriteHandlerMap(sortAndClearUpHandler(handlerList, sheetHolder.getWriteHandlerMap()));
Map<Class, Converter> converterMap = new HashMap<Class, Converter>(sheetHolder.converterMap());
if (table.getCustomConverterMap() != null && !table.getCustomConverterMap().isEmpty()) {
converterMap.putAll(table.getCustomConverterMap());
tableHolder
.setWriteHandlerMap(tableHolder.sortAndClearUpHandler(handlerList, sheetHolder.getWriteHandlerMap()));
Map<Class, Converter> converterMap = new HashMap<Class, Converter>(sheetHolder.getWriteConverterMap());
if (table.getCustomConverterList() != null && !table.getCustomConverterList().isEmpty()) {
for (Converter converter : table.getCustomConverterList()) {
converterMap.put(converter.getClass(), converter);
}
}
setConverterMap(converterMap);
tableHolder.setWriteConverterMap(converterMap);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Table writeHandlerMap:{}", getWriteHandlerMap());
LOGGER.debug("Table writeHandlerMap:{}", tableHolder.getWriteHandlerMap());
}
return tableHolder;
}
/**
* Compatible with old code
*/
@Deprecated
private void compatibleOldCode(com.alibaba.excel.metadata.Table table) {
private static void compatibleOldCode(com.alibaba.excel.metadata.Table table) {
if (table.getTableStyle() != null) {
final TableStyle tableStyle = table.getTableStyle();
if (table.getCustomWriteHandlerList() == null) {

219
src/main/java/com/alibaba/excel/metadata/holder/WorkbookHolder.java

@ -1,5 +1,6 @@
package com.alibaba.excel.metadata.holder;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
@ -11,8 +12,16 @@ import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.converters.DefaultConverterLoader;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.read.listener.ModelBuildEventListener;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.handler.DefaultWriteHandlerLoader;
import com.alibaba.excel.write.handler.WriteHandler;
@ -21,8 +30,9 @@ import com.alibaba.excel.write.handler.WriteHandler;
*
* @author zhuangjiaju
*/
public class WorkbookHolder extends AbstractConfigurationSelector {
public class WorkbookHolder extends AbstractWriteConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(WorkbookHolder.class);
/***
* poi Workbook
*/
@ -40,13 +50,53 @@ public class WorkbookHolder extends AbstractConfigurationSelector {
*/
private OutputStream outputStream;
/**
* Template input stream
* <li>write: Template input stream
* <li>read: Read InputStream
* <p>
* If 'inputStream' and 'file' all not empty,file first
*/
private InputStream inputStream;
/**
* <li>write: Template file
* <li>read: Read file
* <p>
* If 'inputStream' and 'file' all not empty,file first
*/
private InputStream templateInputStream;
private File file;
/**
* Default true
*/
private Boolean autoCloseStream;
/**
* Excel type
*/
private ExcelTypeEnum excelType;
/**
* This object can be read in the Listener {@link AnalysisEventListener#invoke(Object, AnalysisContext)}
* {@link AnalysisContext#getCustom()}
*
*/
private Object readCustomObject;
/**
* A cache that stores temp data to save memory.Default use {@link com.alibaba.excel.cache.Ehcache}
*/
private ReadCache readCache;
/**
* true if date uses 1904 windowing, or false if using 1900 date windowing.
*
* @return
*/
private Boolean use1904windowing;
/**
* Mmandatory use 'inputStream'
*/
private Boolean mandatoryUseInputStream;
/**
* Temporary files when reading excel
*/
private File readTempFile;
/**
* The default is all excel objects.if true , you can use {@link com.alibaba.excel.annotation.ExcelIgnore} ignore a
@ -65,50 +115,91 @@ public class WorkbookHolder extends AbstractConfigurationSelector {
@Deprecated
private com.alibaba.excel.event.WriteHandler writeHandler;
public WorkbookHolder(com.alibaba.excel.metadata.Workbook workbook) {
super();
this.workbookParam = workbook;
this.templateInputStream = workbook.getTemplateInputStream();
this.outputStream = workbook.getOutputStream();
this.templateInputStream = workbook.getTemplateInputStream();
setHead(workbook.getHead());
setClazz(workbook.getClazz());
setNewInitialization(Boolean.TRUE);
if (workbook.getConvertAllFiled() == null) {
this.convertAllFiled = Boolean.TRUE;
} else {
this.convertAllFiled = workbook.getConvertAllFiled();
}
if (workbook.getAutoCloseStream() == null) {
setAutoCloseStream(Boolean.TRUE);
} else {
setAutoCloseStream(workbook.getAutoCloseStream());
}
public static WorkbookHolder buildWriteWorkbookHolder(com.alibaba.excel.metadata.Workbook workbook) {
WorkbookHolder workbookHolder = buildBaseWorkbookHolder(workbook);
workbookHolder.setNewInitialization(Boolean.TRUE);
if (workbook.getNeedHead() == null) {
setNeedHead(Boolean.TRUE);
workbookHolder.setNeedHead(Boolean.TRUE);
} else {
setNeedHead(workbook.getNeedHead());
workbookHolder.setNeedHead(workbook.getNeedHead());
}
if (workbook.getWriteRelativeHeadRowIndex() == null) {
setWriteRelativeHeadRowIndex(0);
workbookHolder.setWriteRelativeHeadRowIndex(0);
} else {
setWriteRelativeHeadRowIndex(workbook.getWriteRelativeHeadRowIndex());
workbookHolder.setWriteRelativeHeadRowIndex(workbook.getWriteRelativeHeadRowIndex());
}
List<WriteHandler> handlerList = new ArrayList<WriteHandler>();
if (workbook.getCustomWriteHandlerList() != null && !workbook.getCustomWriteHandlerList().isEmpty()) {
handlerList.addAll(workbook.getCustomWriteHandlerList());
}
handlerList.addAll(DefaultWriteHandlerLoader.loadDefaultHandler());
setWriteHandlerMap(sortAndClearUpHandler(handlerList, null));
workbookHolder.setWriteHandlerMap(workbookHolder.sortAndClearUpHandler(handlerList, null));
Map<Class, Converter> converterMap = DefaultConverterLoader.loadDefaultWriteConverter();
if (workbook.getCustomConverterMap() != null && !workbook.getCustomConverterMap().isEmpty()) {
converterMap.putAll(workbook.getCustomConverterMap());
if (workbook.getCustomConverterList() != null && !workbook.getCustomConverterList().isEmpty()) {
for (Converter converter : workbook.getCustomConverterList()) {
converterMap.put(converter.getClass(), converter);
}
}
setConverterMap(converterMap);
setHasBeenInitializedSheet(new HashMap<Integer, SheetHolder>());
workbookHolder.setWriteConverterMap(converterMap);
workbookHolder.setHasBeenInitializedSheet(new HashMap<Integer, SheetHolder>());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Wookbook writeHandlerMap:{}", getWriteHandlerMap());
LOGGER.debug("Wookbook writeHandlerMap:{}", workbookHolder.getWriteHandlerMap());
}
return workbookHolder;
}
public static WorkbookHolder buildReadWorkbookHolder(com.alibaba.excel.metadata.Workbook workbook) {
WorkbookHolder workbookHolder = buildBaseWorkbookHolder(workbook);
if (workbook.getFile() == null && workbookHolder.getInputStream() == null) {
throw new ExcelAnalysisException("Read excel 'file' and 'inputStream' cannot be empty at the same time!");
}
workbookHolder.setReadCustomObject(workbook.getReadCustomObject());
workbookHolder.setReadHeadRowNumber(workbook.getReadHeadRowNumber());
workbookHolder.setReadCache(workbook.getReadCache());
Map<ConverterKey, Converter> converterMap = DefaultConverterLoader.loadDefaultReadConverter();
if (workbook.getCustomConverterList() != null && !workbook.getCustomConverterList().isEmpty()) {
for (Converter converter : workbook.getCustomConverterList()) {
converterMap.put(ConverterKey.buildConverterKey(converter), converter);
}
}
workbookHolder.setReadConverterMap(converterMap);
List<ReadListener> readListenerList = new ArrayList<ReadListener>();
readListenerList.add(new ModelBuildEventListener());
if (workbook.getCustomReadListenerList() != null && !workbook.getCustomReadListenerList().isEmpty()) {
readListenerList.addAll(workbook.getCustomReadListenerList());
}
workbookHolder.setReadListenerList(readListenerList);
return workbookHolder;
}
private static WorkbookHolder buildBaseWorkbookHolder(com.alibaba.excel.metadata.Workbook workbook) {
WorkbookHolder workbookHolder = new WorkbookHolder();
workbookHolder.setUse1904windowing(workbook.getUse1904windowing());
workbookHolder.setWorkbookParam(workbook);
workbookHolder.setInputStream(workbook.getInputStream());
workbookHolder.setFile(workbook.getFile());
workbookHolder.setExcelType(workbook.getExcelType());
workbookHolder.setHead(workbook.getHead());
workbookHolder.setClazz(workbook.getClazz());
if (workbook.getConvertAllFiled() == null) {
workbookHolder.setConvertAllFiled(Boolean.TRUE);
} else {
workbookHolder.setConvertAllFiled(workbook.getConvertAllFiled());
}
if (workbook.getAutoCloseStream() == null) {
workbookHolder.setAutoCloseStream(Boolean.TRUE);
} else {
workbookHolder.setAutoCloseStream(workbook.getAutoCloseStream());
}
if (workbook.getAutoTrim() == null) {
workbookHolder.setAutoTrim(Boolean.TRUE);
} else {
workbookHolder.setAutoTrim(workbook.getNeedHead());
}
return workbookHolder;
}
public Workbook getWorkbook() {
@ -143,12 +234,12 @@ public class WorkbookHolder extends AbstractConfigurationSelector {
this.outputStream = outputStream;
}
public InputStream getTemplateInputStream() {
return templateInputStream;
public InputStream getInputStream() {
return inputStream;
}
public void setTemplateInputStream(InputStream templateInputStream) {
this.templateInputStream = templateInputStream;
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public com.alibaba.excel.event.WriteHandler getWriteHandler() {
@ -174,4 +265,60 @@ public class WorkbookHolder extends AbstractConfigurationSelector {
public void setConvertAllFiled(Boolean convertAllFiled) {
this.convertAllFiled = convertAllFiled;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public ExcelTypeEnum getExcelType() {
return excelType;
}
public void setExcelType(ExcelTypeEnum excelType) {
this.excelType = excelType;
}
public Object getReadCustomObject() {
return readCustomObject;
}
public void setReadCustomObject(Object readCustomObject) {
this.readCustomObject = readCustomObject;
}
public ReadCache getReadCache() {
return readCache;
}
public void setReadCache(ReadCache readCache) {
this.readCache = readCache;
}
public Boolean getUse1904windowing() {
return use1904windowing;
}
public void setUse1904windowing(Boolean use1904windowing) {
this.use1904windowing = use1904windowing;
}
public Boolean getMandatoryUseInputStream() {
return mandatoryUseInputStream;
}
public void setMandatoryUseInputStream(Boolean mandatoryUseInputStream) {
this.mandatoryUseInputStream = mandatoryUseInputStream;
}
public File getReadTempFile() {
return readTempFile;
}
public void setReadTempFile(File readTempFile) {
this.readTempFile = readTempFile;
}
}

4
src/main/java/com/alibaba/excel/metadata/holder/ConfigurationSelector.java → src/main/java/com/alibaba/excel/metadata/holder/WriteConfiguration.java

@ -13,7 +13,7 @@ import com.alibaba.excel.write.handler.WriteHandler;
*
* @author zhuangjiaju
**/
public interface ConfigurationSelector {
public interface WriteConfiguration {
/**
* What handler does the currently operated cell need to execute
@ -27,7 +27,7 @@ public interface ConfigurationSelector {
*
* @return
*/
Map<Class, Converter> converterMap();
Map<Class, Converter> writeConverterMap();
/**
* Whether a header is required for the currently operated cell

14
src/main/java/com/alibaba/excel/metadata/property/ExcelContentProperty.java

@ -19,6 +19,12 @@ public class ExcelContentProperty {
private CellStyleProperty cellStyleProperty;
private DateTimeFormatProperty dateTimeFormatProperty;
private NumberFormatProperty numberFormatProperty;
/**
* true if date uses 1904 windowing, or false if using 1900 date windowing.
*
* @return
*/
private Boolean use1904windowing;
public Field getField() {
return field;
@ -59,4 +65,12 @@ public class ExcelContentProperty {
public void setNumberFormatProperty(NumberFormatProperty numberFormatProperty) {
this.numberFormatProperty = numberFormatProperty;
}
public Boolean getUse1904windowing() {
return use1904windowing;
}
public void setUse1904windowing(Boolean use1904windowing) {
this.use1904windowing = use1904windowing;
}
}

60
src/main/java/com/alibaba/excel/metadata/property/ExcelHeadProperty.java

@ -23,6 +23,8 @@ import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellRange;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.holder.WorkbookHolder;
import com.alibaba.excel.util.StringUtils;
/**
* Define the header attribute of excel
@ -49,7 +51,6 @@ public class ExcelHeadProperty {
* Configuration header information
*/
private Map<Integer, Head> headMap;
/**
* Configuration column information
*/
@ -57,7 +58,7 @@ public class ExcelHeadProperty {
private RowHeightProperty headRowHeightProperty;
private RowHeightProperty contentRowHeightProperty;
public ExcelHeadProperty(Class headClazz, List<List<String>> head, Boolean convertAllFiled) {
public ExcelHeadProperty(Class headClazz, List<List<String>> head, WorkbookHolder workbookHolder) {
this.headClazz = headClazz;
headMap = new TreeMap<Integer, Head>();
contentPropertyMap = new TreeMap<Integer, ExcelContentProperty>();
@ -71,27 +72,18 @@ public class ExcelHeadProperty {
headKind = HeadKindEnum.STRING;
} else {
// convert headClazz to head
initColumnProperties(convertAllFiled);
initColumnProperties(workbookHolder);
}
initHeadRowNumber();
LOGGER.info("The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is {}", headKind);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is {}", headKind);
}
if (!hasHead()) {
LOGGER.warn(
"The table has no header set and all annotations will not be read.If you want to use annotations, please use set head class in ExcelWriterBuilder/ExcelWriterSheetBuilder/ExcelWriterTableBuilder");
}
}
public static ExcelHeadProperty buildExcelHeadProperty(ExcelHeadProperty excelHeadProperty, Class clazz,
List<String> headOneRow) {
if (excelHeadProperty == null) {
return new ExcelHeadProperty(clazz, new ArrayList<List<String>>(), false);
}
if (headOneRow != null) {
excelHeadProperty.appendOneRow(headOneRow);
}
return excelHeadProperty;
}
private void initHeadRowNumber() {
headRowNumber = 0;
for (Head head : headMap.values()) {
@ -112,7 +104,7 @@ public class ExcelHeadProperty {
}
}
private void initColumnProperties(Boolean convertAllFiled) {
private void initColumnProperties(WorkbookHolder workbookHolder) {
if (headClazz == null) {
return;
}
@ -135,7 +127,7 @@ public class ExcelHeadProperty {
continue;
}
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
if (excelProperty == null && !convertAllFiled) {
if (excelProperty == null && (workbookHolder == null || !workbookHolder.getConvertAllFiled())) {
continue;
}
if (excelProperty == null || excelProperty.index() < 0) {
@ -160,22 +152,23 @@ public class ExcelHeadProperty {
int index = 0;
for (Field field : defaultFieldList) {
while (customFiledMap.containsKey(index)) {
initOneColumnProperty(index, customFiledMap.get(index), headStyle, contentStyle, columnWidth);
initOneColumnProperty(index, customFiledMap.get(index), headStyle, contentStyle, columnWidth,
workbookHolder);
customFiledMap.remove(index);
index++;
}
initOneColumnProperty(index, field, headStyle, contentStyle, columnWidth);
initOneColumnProperty(index, field, headStyle, contentStyle, columnWidth, workbookHolder);
index++;
}
for (Map.Entry<Integer, Field> entry : customFiledMap.entrySet()) {
initOneColumnProperty(index, entry.getValue(), headStyle, contentStyle, columnWidth);
initOneColumnProperty(index, entry.getValue(), headStyle, contentStyle, columnWidth, workbookHolder);
index++;
}
headKind = HeadKindEnum.CLASS;
}
private void initOneColumnProperty(int index, Field field, HeadStyle parentHeadStyle,
ContentStyle parentContentStyle, ColumnWidth parentColumnWidth) {
ContentStyle parentContentStyle, ColumnWidth parentColumnWidth, WorkbookHolder workbookHolder) {
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
List<String> tmpHeadList = new ArrayList<String>();
@ -184,6 +177,9 @@ public class ExcelHeadProperty {
} else {
tmpHeadList.add(field.getName());
}
if (tmpHeadList.isEmpty() || StringUtils.isEmpty(tmpHeadList.get(0))) {
tmpHeadList.add(field.getName());
}
Head head = new Head(index, field.getName(), tmpHeadList);
HeadStyle headStyle = field.getAnnotation(HeadStyle.class);
if (headStyle == null) {
@ -211,26 +207,12 @@ public class ExcelHeadProperty {
excelContentProperty
.setNumberFormatProperty(NumberFormatProperty.build(field.getAnnotation(NumberFormat.class)));
headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty);
}
/**
* Add one more head under the last head
*/
public void appendOneRow(List<String> row) {
for (int i = 0; i < row.size(); i++) {
String rowData = row.get(i);
// join
if (headMap.containsKey(i)) {
headMap.get(i).getHeadNameList().add(rowData);
} else {
// create and join
int index = ((TreeMap<Integer, Head>)headMap).lastKey() + 1;
headMap.put(index, new Head(i, null, rowData));
}
if (workbookHolder != null && workbookHolder.getReadGlobalProperty() != null) {
excelContentProperty.setGlobalProperty(workbookHolder.getReadGlobalProperty());
}
initHeadRowNumber();
headMap.put(index, head);
contentPropertyMap.put(index, excelContentProperty);
}
public Class getHeadClazz() {

21
src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java

@ -0,0 +1,21 @@
package com.alibaba.excel.read.builder;
import com.alibaba.excel.metadata.Workbook;
/**
* Build ExcelWriter
*
* @author zhuangjiaju
*/
public class ExcelReaderBuilder {
/**
* Workbook
*/
private Workbook workbook;
public ExcelReaderBuilder() {
this.workbook = new Workbook();
}
}

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

@ -0,0 +1,98 @@
package com.alibaba.excel.read.listener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterKey;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.enums.HeadKindEnum;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.holder.ReadConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.metadata.property.ExcelHeadProperty;
import net.sf.cglib.beans.BeanMap;
/**
* Convert to the object the user needs
*
* @author jipengfei
*/
public class ModelBuildEventListener extends AnalysisEventListener<List<CellData>> {
@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {}
@Override
public void invoke(List<CellData> data, AnalysisContext context) {
ReadConfiguration readConfiguration = context.currentConfiguration();
if (HeadKindEnum.CLASS.equals(context.currentSheetHolder().getExcelHeadProperty().getHeadKind())) {
context.setCurrentRowAnalysisResult(buildUserModel(data, readConfiguration));
return;
}
context.setCurrentRowAnalysisResult(buildStringList(data, readConfiguration));
}
private Object buildStringList(List<CellData> data, ReadConfiguration readConfiguration) {
List<String> list = new ArrayList<String>();
for (CellData cellData : data) {
list.add((String)convertValue(cellData, String.class, null, readConfiguration.readConverterMap()));
}
return list;
}
private Object buildUserModel(List<CellData> data, ReadConfiguration readConfiguration) {
ExcelHeadProperty excelHeadProperty = readConfiguration.excelHeadProperty();
Object resultModel;
try {
resultModel = excelHeadProperty.getHeadClazz().newInstance();
} catch (Exception e) {
throw new ExcelDataConvertException("Can not instance class: " + excelHeadProperty.getHeadClazz().getName(),
e);
}
Map<String, Object> map = new HashMap<String, Object>();
Map<Integer, Head> headMap = excelHeadProperty.getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMap = excelHeadProperty.getContentPropertyMap();
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
Integer index = entry.getKey();
if (index >= data.size()) {
continue;
}
CellData cellData = data.get(index);
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
continue;
}
ExcelContentProperty excelContentProperty = contentPropertyMap.get(index);
Object value = convertValue(cellData, excelContentProperty.getField().getClass(), excelContentProperty,
readConfiguration.readConverterMap());
if (value != null) {
map.put(excelContentProperty.getField().getName(), value);
}
}
BeanMap.create(resultModel).putAll(map);
return resultModel;
}
private Object convertValue(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map<ConverterKey, Converter> readConverterMap) {
Converter converter = readConverterMap.get(ConverterKey.buildConverterKey(clazz, cellData.getType()));
if (converter == null) {
throw new ExcelDataConvertException(
"Converter not found, convert " + cellData.getType() + " to " + clazz.getName());
}
try {
return converter.convertToJavaData(cellData, contentProperty);
} catch (Exception e) {
throw new ExcelDataConvertException("Convert data " + cellData + " to " + clazz + " error ", e);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {}
}

19
src/main/java/com/alibaba/excel/event/ReadListener.java → src/main/java/com/alibaba/excel/read/listener/ReadListener.java

@ -1,6 +1,7 @@
package com.alibaba.excel.event;
package com.alibaba.excel.read.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.Listener;
/**
* Interface to listen for read results
@ -19,14 +20,14 @@ public interface ReadListener<T> extends Listener {
void onException(Exception exception, AnalysisContext context) throws Exception;
/**
* when analysis one row trigger invoke function
* when analysis one row trigger invoke function.
*
* @param object
* one row value
* @param data
* one row value. Is is same as {@link AnalysisContext#currentRowAnalysisResult()}
* @param context
* analysis context
*/
void invoke(T object, AnalysisContext context);
void invoke(T data, AnalysisContext context);
/**
* if have something to do after all analysis
@ -34,4 +35,12 @@ public interface ReadListener<T> extends Listener {
* @param context
*/
void doAfterAllAnalysed(AnalysisContext context);
/**
* Verify that there is another piece of data.You can stop the read by returning false
*
* @param context
* @return
*/
boolean hasNext(AnalysisContext context);
}

35
src/main/java/com/alibaba/excel/read/listener/ReadListenerRegistryCenter.java

@ -0,0 +1,35 @@
package com.alibaba.excel.read.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.AnalysisFinishEvent;
/**
* Registry center.
*
* @author jipengfei
*/
public interface ReadListenerRegistryCenter {
/**
* register
*
* @param listener
*/
void register(AnalysisEventListener listener);
/**
* Parse one row to notify all event listeners
*
* @param event
* parse event
* @param analysisContext
*/
void notifyEndOneRow(AnalysisFinishEvent event, AnalysisContext analysisContext);
/**
*
* @param analysisContext
*/
void notifyAfterAllAnalysed(AnalysisContext analysisContext);
}

41
src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java

@ -1,10 +1,10 @@
package com.alibaba.excel.support;
import org.apache.poi.poifs.filesystem.FileMagic;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.poifs.filesystem.FileMagic;
/**
* @author jipengfei
*/
@ -18,6 +18,24 @@ public enum ExcelTypeEnum {
this.setValue(value);
}
public static ExcelTypeEnum valueOf(InputStream inputStream) {
try {
if (!inputStream.markSupported()) {
return null;
}
FileMagic fileMagic = FileMagic.valueOf(inputStream);
if (FileMagic.OLE2.equals(fileMagic)) {
return XLS;
}
if (FileMagic.OOXML.equals(fileMagic)) {
return XLSX;
}
return null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String getValue() {
return value;
}
@ -25,23 +43,4 @@ public enum ExcelTypeEnum {
public void setValue(String value) {
this.value = value;
}
public static ExcelTypeEnum valueOf(InputStream inputStream){
return XLSX;
// try {
// if (!inputStream.markSupported()) {
// return null;
// }
// FileMagic fileMagic = FileMagic.valueOf(inputStream);
// if(FileMagic.OLE2.equals(fileMagic)){
// return XLS;
// }
// if(FileMagic.OOXML.equals(fileMagic)){
// return XLSX;
// }
// return null;
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
}
}

45
src/main/java/com/alibaba/excel/util/POITempFile.java → src/main/java/com/alibaba/excel/util/FileUtils.java

@ -1,13 +1,19 @@
package com.alibaba.excel.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import com.alibaba.excel.exception.ExcelAnalysisException;
/**
*
* @author jipengfei
*/
public class POITempFile {
public class FileUtils {
private static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
@ -15,9 +21,44 @@ public class POITempFile {
private static final String CACHE = "excache";
/**
* Write inputStream to file
*
* @param file
* @param inputStream
*/
public static void writeToFile(File file, InputStream inputStream) {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
int bytesRead;
byte[] buffer = new byte[8192];
while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
throw new ExcelAnalysisException("Can not create temporary file!", e);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
throw new ExcelAnalysisException("Can not close 'outputStream'!", e);
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new ExcelAnalysisException("Can not close 'inputStream'", e);
}
}
}
}
/**
*/
public static void createPOIFilesDirectory() {
public static void createPoiFilesDirectory() {
createTmpDirectory(POIFILES);
}

2
src/main/java/com/alibaba/excel/util/NumberUtils.java

@ -22,7 +22,7 @@ public class NumberUtils {
* @return
*/
public static String format(Number num, ExcelContentProperty contentProperty) {
if (contentProperty.getNumberFormatProperty() == null
if (contentProperty == null || contentProperty.getNumberFormatProperty() == null
|| StringUtils.isEmpty(contentProperty.getNumberFormatProperty().getFormat())) {
return num.toString();
}

28
src/main/java/com/alibaba/excel/util/WorkBookUtil.java

@ -3,6 +3,7 @@ package com.alibaba.excel.util;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
@ -12,6 +13,7 @@ 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.metadata.holder.WorkbookHolder;
import com.alibaba.excel.support.ExcelTypeEnum;
/**
@ -20,16 +22,24 @@ import com.alibaba.excel.support.ExcelTypeEnum;
*/
public class WorkBookUtil {
public static Workbook createWorkBook(com.alibaba.excel.metadata.Workbook workbookParam) throws IOException {
Workbook workbook;
if (ExcelTypeEnum.XLS.equals(workbookParam.getExcelType())) {
workbook = (workbookParam.getTemplateInputStream() == null) ? new HSSFWorkbook()
: new HSSFWorkbook(new POIFSFileSystem(workbookParam.getTemplateInputStream()));
} else {
workbook = (workbookParam.getTemplateInputStream() == null) ? new SXSSFWorkbook(500)
: new SXSSFWorkbook(new XSSFWorkbook(workbookParam.getTemplateInputStream()));
public static Workbook createWorkBook(WorkbookHolder workbookHolder)
throws IOException, InvalidFormatException {
if (ExcelTypeEnum.XLSX.equals(workbookHolder.getExcelType())) {
if (workbookHolder.getFile() != null) {
return new SXSSFWorkbook(new XSSFWorkbook(workbookParam.getFile()));
}
if (workbookParam.getInputStream() != null) {
return new SXSSFWorkbook(new XSSFWorkbook(workbookParam.getInputStream()));
}
return new SXSSFWorkbook(500);
}
return workbook;
if (workbookParam.getFile() != null) {
return new HSSFWorkbook(new POIFSFileSystem(workbookParam.getFile()));
}
if (workbookParam.getInputStream() != null) {
return new HSSFWorkbook(new POIFSFileSystem(workbookParam.getInputStream()));
}
return new HSSFWorkbook();
}
public static Sheet createSheet(Workbook workbook, com.alibaba.excel.metadata.Sheet sheet) {

34
src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java

@ -17,7 +17,7 @@ import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.metadata.holder.ConfigurationSelector;
import com.alibaba.excel.metadata.holder.WriteConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.POITempFile;
@ -47,8 +47,8 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
org.apache.poi.ss.usermodel.Sheet currentSheet = context.currentSheetHolder().getSheet();
int rowNum = currentSheet.getLastRowNum();
if (context.currentConfigurationSelector().isNew()) {
rowNum += context.currentConfigurationSelector().writeRelativeHeadRowIndex();
if (context.currentConfiguration().isNew()) {
rowNum += context.currentConfiguration().writeRelativeHeadRowIndex();
}
for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) {
int n = relativeRowIndex + rowNum + 1;
@ -92,7 +92,7 @@ public class ExcelBuilderImpl implements ExcelBuilder {
private void beforeRowCreate(int rowIndex, int relativeRowIndex) {
List<WriteHandler> handlerList =
context.currentConfigurationSelector().writeHandlerMap().get(RowWriteHandler.class);
context.currentConfiguration().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -106,7 +106,7 @@ public class ExcelBuilderImpl implements ExcelBuilder {
private void afterRowCreate(Row row, int relativeRowIndex) {
List<WriteHandler> handlerList =
context.currentConfigurationSelector().writeHandlerMap().get(RowWriteHandler.class);
context.currentConfiguration().writeHandlerMap().get(RowWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -125,7 +125,7 @@ public class ExcelBuilderImpl implements ExcelBuilder {
if (CollectionUtils.isEmpty(oneRowData)) {
return;
}
Map<Integer, Head> headMap = context.currentConfigurationSelector().excelHeadProperty().getHeadMap();
Map<Integer, Head> headMap = context.currentConfiguration().excelHeadProperty().getHeadMap();
int dataIndex = 0;
int cellIndex = 0;
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
@ -153,17 +153,17 @@ public class ExcelBuilderImpl implements ExcelBuilder {
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
Object value = oneRowData.get(dataIndex);
converterAndSet(context.currentConfigurationSelector(), value.getClass(), cell, value, null);
converterAndSet(context.currentConfiguration(), value.getClass(), cell, value, null);
afterCellCreate(head, cell, relativeRowIndex);
}
private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex) {
ConfigurationSelector currentConfigurationSelector = context.currentConfigurationSelector();
WriteConfiguration currentWriteConfiguration = context.currentConfiguration();
BeanMap beanMap = BeanMap.create(oneRowData);
Set<String> beanMapHandledSet = new HashSet<String>();
Map<Integer, Head> headMap = context.currentConfigurationSelector().excelHeadProperty().getHeadMap();
Map<Integer, Head> headMap = context.currentConfiguration().excelHeadProperty().getHeadMap();
Map<Integer, ExcelContentProperty> contentPropertyMap =
context.currentConfigurationSelector().excelHeadProperty().getContentPropertyMap();
context.currentConfiguration().excelHeadProperty().getContentPropertyMap();
int cellIndex = 0;
for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) {
cellIndex = entry.getKey();
@ -176,7 +176,7 @@ public class ExcelBuilderImpl implements ExcelBuilder {
beforeCellCreate(row, head, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex);
Object value = beanMap.get(name);
converterAndSet(currentConfigurationSelector, excelContentProperty.getField().getType(), cell, value,
converterAndSet(currentWriteConfiguration, excelContentProperty.getField().getType(), cell, value,
excelContentProperty);
afterCellCreate(head, cell, relativeRowIndex);
beanMapHandledSet.add(name);
@ -195,14 +195,14 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
beforeCellCreate(row, null, relativeRowIndex);
Cell cell = WorkBookUtil.createCell(row, cellIndex++);
converterAndSet(currentConfigurationSelector, entry.getValue().getClass(), cell, entry.getValue(), null);
converterAndSet(currentWriteConfiguration, entry.getValue().getClass(), cell, entry.getValue(), null);
afterCellCreate(null, cell, relativeRowIndex);
}
}
private void beforeCellCreate(Row row, Head head, int relativeRowIndex) {
List<WriteHandler> handlerList =
context.currentConfigurationSelector().writeHandlerMap().get(CellWriteHandler.class);
context.currentConfiguration().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -217,7 +217,7 @@ public class ExcelBuilderImpl implements ExcelBuilder {
private void afterCellCreate(Head head, Cell cell, int relativeRowIndex) {
List<WriteHandler> handlerList =
context.currentConfigurationSelector().writeHandlerMap().get(CellWriteHandler.class);
context.currentConfiguration().writeHandlerMap().get(CellWriteHandler.class);
if (handlerList == null || handlerList.isEmpty()) {
return;
}
@ -232,12 +232,12 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
}
private void converterAndSet(ConfigurationSelector currentConfigurationSelector, Class clazz, Cell cell,
Object value, ExcelContentProperty excelContentProperty) {
private void converterAndSet(WriteConfiguration currentWriteConfiguration, Class clazz, Cell cell,
Object value, ExcelContentProperty excelContentProperty) {
if (value == null) {
return;
}
Converter converter = currentConfigurationSelector.converterMap().get(clazz);
Converter converter = currentWriteConfiguration.converterMap().get(clazz);
if (converter == null) {
throw new ExcelDataConvertException(
"Can not find 'Converter' support class " + clazz.getSimpleName() + ".");

22
src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java

@ -1,7 +1,6 @@
package com.alibaba.excel.write.builder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
@ -170,25 +169,22 @@ public class ExcelWriterBuilder {
return outputFile(new File(outputUri));
}
public ExcelWriterBuilder withTemplate(InputStream templateInputStream) {
workbook.setTemplateInputStream(templateInputStream);
public ExcelWriterBuilder withTemplate(InputStream inputStream) {
workbook.setInputStream(inputStream);
return this;
}
public ExcelWriterBuilder withTemplate(File templateFile) {
try {
return withTemplate(new FileInputStream(templateFile));
} catch (FileNotFoundException e) {
throw new ExcelGenerateException("Can not create file", e);
}
public ExcelWriterBuilder withTemplate(File file) {
workbook.setFile(file);
return this;
}
public ExcelWriterBuilder withTemplate(String templatePathName) {
return withTemplate(new File(templatePathName));
public ExcelWriterBuilder withTemplate(String pathName) {
return withTemplate(new File(pathName));
}
public ExcelWriterBuilder withTemplate(URI templateUri) {
return withTemplate(new File(templateUri));
public ExcelWriterBuilder withTemplate(URI uri) {
return withTemplate(new File(uri));
}
/**

Loading…
Cancel
Save