Browse Source

Merge pull request #431 from clevertension/refactor

hudge refactor to support v2.0
bugfix
jipengfei-jpf 5 years ago committed by GitHub
parent
commit
0883bdf9f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/main/java/com/alibaba/excel/EasyExcelFactory.java
  2. 119
      src/main/java/com/alibaba/excel/ExcelReader.java
  3. 134
      src/main/java/com/alibaba/excel/ExcelWriter.java
  4. 110
      src/main/java/com/alibaba/excel/analysis/BaseSaxAnalyser.java
  5. 15
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyser.java
  6. 51
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
  7. 27
      src/main/java/com/alibaba/excel/analysis/v03/AbstractXlsRecordHandler.java
  8. 13
      src/main/java/com/alibaba/excel/analysis/v03/XlsRecordHandler.java
  9. 277
      src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
  10. 71
      src/main/java/com/alibaba/excel/analysis/v03/handlers/BOFRecordHandler.java
  11. 37
      src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankOrErrorRecordHandler.java
  12. 71
      src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java
  13. 30
      src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java
  14. 30
      src/main/java/com/alibaba/excel/analysis/v03/handlers/MissingCellDummyRecordHandler.java
  15. 32
      src/main/java/com/alibaba/excel/analysis/v03/handlers/NoteRecordHandler.java
  16. 36
      src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java
  17. 31
      src/main/java/com/alibaba/excel/analysis/v03/handlers/RKRecordHandler.java
  18. 39
      src/main/java/com/alibaba/excel/analysis/v03/handlers/SSTRecordHandler.java
  19. 11
      src/main/java/com/alibaba/excel/analysis/v07/XlsxCellHandler.java
  20. 29
      src/main/java/com/alibaba/excel/analysis/v07/XlsxHandlerFactory.java
  21. 130
      src/main/java/com/alibaba/excel/analysis/v07/XlsxRowHandler.java
  22. 11
      src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java
  23. 36
      src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java
  24. 121
      src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java
  25. 37
      src/main/java/com/alibaba/excel/analysis/v07/handlers/ProcessResultCellHandler.java
  26. 21
      src/main/java/com/alibaba/excel/context/AnalysisContext.java
  27. 37
      src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java
  28. 300
      src/main/java/com/alibaba/excel/context/WriteContext.java
  29. 311
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  30. 33
      src/main/java/com/alibaba/excel/converters/BigDecimalConverter.java
  31. 42
      src/main/java/com/alibaba/excel/converters/BooleanConverter.java
  32. 13
      src/main/java/com/alibaba/excel/converters/Converter.java
  33. 8
      src/main/java/com/alibaba/excel/converters/ConverterRegistryCenter.java
  34. 55
      src/main/java/com/alibaba/excel/converters/DateConverter.java
  35. 33
      src/main/java/com/alibaba/excel/converters/DoubleConverter.java
  36. 31
      src/main/java/com/alibaba/excel/converters/FloatConverter.java
  37. 33
      src/main/java/com/alibaba/excel/converters/IntegerConverter.java
  38. 33
      src/main/java/com/alibaba/excel/converters/LongConverter.java
  39. 31
      src/main/java/com/alibaba/excel/converters/StringConverter.java
  40. 2
      src/main/java/com/alibaba/excel/event/AnalysisEventListener.java
  41. 12
      src/main/java/com/alibaba/excel/event/AnalysisEventRegistryCenter.java
  42. 5
      src/main/java/com/alibaba/excel/event/AnalysisFinishEvent.java
  43. 29
      src/main/java/com/alibaba/excel/event/EachRowAnalysisFinishEvent.java
  44. 44
      src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java
  45. 34
      src/main/java/com/alibaba/excel/event/OneRowAnalysisFinishEvent.java
  46. 14
      src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java
  47. 10
      src/main/java/com/alibaba/excel/parameter/GenerateParam.java
  48. 126
      src/main/java/com/alibaba/excel/util/TypeUtil.java
  49. 22
      src/main/java/com/alibaba/excel/util/WorkBookUtil.java
  50. 13
      src/main/java/com/alibaba/excel/write/ExcelBuilder.java
  51. 89
      src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java
  52. 8
      src/main/java/com/alibaba/excel/write/MergeStrategy.java
  53. 8
      src/test/java/com/alibaba/easyexcel/test/ReadTest.java
  54. 148
      src/test/java/com/alibaba/easyexcel/test/WriteTest.java
  55. 2
      src/test/java/com/alibaba/easyexcel/test/model/WriteModel.java
  56. 4
      src/test/java/com/alibaba/easyexcel/test/util/FileUtil.java

14
src/main/java/com/alibaba/excel/EasyExcelFactory.java

@ -27,7 +27,7 @@ public class EasyExcelFactory {
*/
public static List<Object> read(InputStream in, Sheet sheet) {
final List<Object> rows = new ArrayList<Object>();
new ExcelReader(in, null, new AnalysisEventListener() {
new ExcelReader(in, null, new AnalysisEventListener<Object>() {
@Override
public void invoke(Object object, AnalysisContext context) {
rows.add(object);
@ -65,7 +65,7 @@ public class EasyExcelFactory {
/**
* Get ExcelWriter
*
* @param outputStream the java OutputStream you wish to write the data to.
* @param outputStream the java OutputStream you wish to write the value to.
* @return new ExcelWriter.
*/
public static ExcelWriter getWriter(OutputStream outputStream) {
@ -75,7 +75,7 @@ public class EasyExcelFactory {
/**
* Get ExcelWriter
*
* @param outputStream the java OutputStream you wish to write the data to.
* @param outputStream the java OutputStream you wish to write the value to.
* @param typeEnum 03 or 07
* @param needHead Do you need to write the header to the file?
* @return new ExcelWriter
@ -87,9 +87,9 @@ public class EasyExcelFactory {
/**
* Get ExcelWriter with a template file
*
* @param temp Append data after a POI file , Can be nullthe template POI filesystem that contains the
* @param temp Append value after a POI file , Can be nullthe template POI filesystem that contains the
* Workbook stream)
* @param outputStream the java OutputStream you wish to write the data to
* @param outputStream the java OutputStream you wish to write the value to
* @param typeEnum 03 or 07
* @return new ExcelWriter
*/
@ -101,9 +101,9 @@ public class EasyExcelFactory {
/**
* Get ExcelWriter with a template file
*
* @param temp Append data after a POI file , Can be nullthe template POI filesystem that contains the
* @param temp Append value after a POI file , Can be nullthe template POI filesystem that contains the
* Workbook stream)
* @param outputStream the java OutputStream you wish to write the data to
* @param outputStream the java OutputStream you wish to write the value to
* @param typeEnum 03 or 07
* @param needHead
* @param handler User-defined callback

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

@ -1,17 +1,18 @@
package com.alibaba.excel;
import java.io.InputStream;
import java.util.List;
import com.alibaba.excel.analysis.ExcelAnalyser;
import com.alibaba.excel.analysis.ExcelAnalyserImpl;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.parameter.AnalysisParam;
import com.alibaba.excel.support.ExcelTypeEnum;
import java.io.InputStream;
import java.util.List;
/**
* Excel readers are all read in event mode.
*
@ -22,38 +23,52 @@ public class ExcelReader {
/**
* Analyser
*/
private ExcelAnalyser analyser ;
private ExcelAnalyser analyser;
/**
* Create new reader
*
* @param in the POI filesystem that contains the Workbook stream
* @param in the POI filesystem that contains the Workbook stream
* @param excelTypeEnum 03 or 07
* @param customContent {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @param customContent
* {@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 customContent {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @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
*/
public ExcelReader(InputStream in, Object customContent,
AnalysisEventListener eventListener) {
this(in, customContent, eventListener, true);
public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener) {
this(in, customContent, eventListener, null, true);
}
/**
* Create new reader
*
* @param param old param Deprecated
* @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
*/
public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener,
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.
*/
@Deprecated
@ -64,43 +79,65 @@ 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 excelTypeEnum 03 or 07
* @param customContent {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @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.
* @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) {
validateParam(in, eventListener);
analyser = new ExcelAnalyserImpl(in, excelTypeEnum, customContent, eventListener, trim);
AnalysisEventListener eventListener, boolean trim) {
this(in, excelTypeEnum, customContent, eventListener, null, trim);
}
/**
* Create new reader
*
* @param in
* @param customContent {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @param customContent
* {@link AnalysisEventListener#invoke(Object, AnalysisContext) }AnalysisContext
* @param eventListener
* @param trim The content of the form is empty and needs to be empty. The purpose is to be fault-tolerant,
* because there are often table contents with spaces that can not be converted into custom
* types. For example: '1234 ' contain a space cannot be converted to int.
* @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, boolean trim) {
ExcelTypeEnum excelTypeEnum = ExcelTypeEnum.valueOf(in);
public ExcelReader(InputStream in, Object customContent, AnalysisEventListener eventListener,
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) {
this(in, ExcelTypeEnum.valueOf(in), null, eventListener, null, trim);
}
public ExcelReader(InputStream in, ExcelTypeEnum excelTypeEnum, Object customContent,
AnalysisEventListener eventListener, List<Converter> converters, boolean trim) {
validateParam(in, eventListener);
analyser =new ExcelAnalyserImpl(in, excelTypeEnum, customContent, eventListener, trim);
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) {
analyser.getAnalysisContext().getConverterRegistryCenter().register(c);
}
}
}
/**
* Parse all sheet content by default
*/
public void read() {
analyser.analysis();
read(null, null);;
}
/**
@ -109,19 +146,23 @@ public class ExcelReader {
* @param sheet Read sheet
*/
public void read(Sheet sheet) {
analyser.analysis(sheet);
read(sheet, null);
}
/**
* Parse the specified sheet
*
* @param sheet Read sheet
* @param clazz object parsed into each row of data
* @param sheet Read sheet
* @param clazz object parsed into each row of value
*/
@Deprecated
public void read(Sheet sheet, Class<? extends BaseRowModel> clazz) {
sheet.setClazz(clazz);
analyser.analysis(sheet);
analyser.beforeAnalysis();
if (sheet != null) {
sheet.setClazz(clazz);
analyser.analysis(sheet);
} else {
analyser.analysis();
}
}
/**
@ -133,13 +174,17 @@ public class ExcelReader {
return analyser.getSheets();
}
public AnalysisContext getAnalysisContext() {
return analyser.getAnalysisContext();
}
/**
* validate param
*
* @param in
* @param eventListener
*/
private void validateParam(InputStream in, AnalysisEventListener eventListener) {
private void validateParam(InputStream in, AnalysisEventListener eventListener) {
if (eventListener == null) {
throw new IllegalArgumentException("AnalysisEventListener can not null");
} else if (in == null) {

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

@ -1,5 +1,18 @@
package com.alibaba.excel;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import com.alibaba.excel.converters.BooleanConverter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.converters.DateConverter;
import com.alibaba.excel.converters.DoubleConverter;
import com.alibaba.excel.converters.FloatConverter;
import com.alibaba.excel.converters.IntegerConverter;
import com.alibaba.excel.converters.LongConverter;
import com.alibaba.excel.converters.StringConverter;
import com.alibaba.excel.event.WriteHandler;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
@ -8,18 +21,17 @@ import com.alibaba.excel.parameter.GenerateParam;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.ExcelBuilder;
import com.alibaba.excel.write.ExcelBuilderImpl;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import com.alibaba.excel.write.MergeStrategy;
/**
* Excel Writer This tool is used to write data out to Excel via POI.
* This object can perform the following two functions.
* Excel Writer This tool is used to write value out to Excel via POI. This object can perform the
* following two functions.
*
* <pre>
* 1. Create a new empty Excel workbook, write the data to the stream after the data is filled.
* 1. Create a new empty Excel workbook, write the value to the stream after the value is filled.
* 2. Edit existing Excel, write the original Excel file, or write it to other places.}
* </pre>
*
* @author jipengfei
*/
public class ExcelWriter {
@ -28,7 +40,8 @@ public class ExcelWriter {
/**
* Create new writer
* @param outputStream the java OutputStream you wish to write the data to
*
* @param outputStream the java OutputStream you wish to write the value to
* @param typeEnum 03 or 07
*/
public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum) {
@ -43,46 +56,80 @@ public class ExcelWriter {
*/
@Deprecated
public ExcelWriter(GenerateParam generateParam) {
this(generateParam.getOutputStream(), generateParam.getType(), true);
this(generateParam.getOutputStream(), generateParam.getType(), generateParam.isNeedHead());
this.objectClass = generateParam.getClazz();
}
/**
*
* Create new writer
* @param outputStream the java OutputStream you wish to write the data to
*
* @param outputStream the java OutputStream you wish to write the value to
* @param typeEnum 03 or 07
* @param needHead Do you need to write the header to the file?
*/
public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum, boolean needHead) {
excelBuilder = new ExcelBuilderImpl(null, outputStream, typeEnum, needHead, null);
this(null, outputStream, typeEnum, needHead, null, null);
}
/**
* Create new writer
* @param templateInputStream Append data after a POI file ,Can be nullthe template POI filesystem that contains the Workbook stream)
* @param outputStream the java OutputStream you wish to write the data to
* Create new writer
*
* @param templateInputStream Append value after a POI file ,Can be nullthe template POI
* filesystem that contains the Workbook stream)
* @param outputStream the java OutputStream you wish to write the value to
* @param typeEnum 03 or 07
*/
public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,Boolean needHead) {
excelBuilder = new ExcelBuilderImpl(templateInputStream,outputStream, typeEnum, needHead, null);
public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,
Boolean needHead) {
this(templateInputStream, outputStream, typeEnum, needHead, null, null);
}
/**
* Create new writer
* @param templateInputStream Append data after a POI file ,Can be nullthe template POI filesystem that contains the Workbook stream)
* @param outputStream the java OutputStream you wish to write the data to
* Create new writer
*
* @param templateInputStream Append value after a POI file ,Can be nullthe template POI
* filesystem that contains the Workbook stream)
* @param outputStream the java OutputStream you wish to write the value to
* @param typeEnum 03 or 07
* @param writeHandler User-defined callback
*/
public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum, Boolean needHead,
WriteHandler writeHandler) {
excelBuilder = new ExcelBuilderImpl(templateInputStream,outputStream, typeEnum, needHead,writeHandler);
public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,
Boolean needHead, WriteHandler writeHandler) {
this(templateInputStream, outputStream, typeEnum, needHead, writeHandler, null);
}
public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,
Boolean needHead, WriteHandler writeHandler, List<Converter> converters) {
excelBuilder = new ExcelBuilderImpl(templateInputStream, outputStream, typeEnum, needHead, writeHandler,
converters);
if (this.excelBuilder instanceof ConverterRegistryCenter) {
ConverterRegistryCenter registryCenter = (ConverterRegistryCenter)this.excelBuilder;
initConverters(registryCenter, converters);
}
}
private void initConverters(ConverterRegistryCenter registryCenter, List<Converter> converters) {
registerDefaultConverters(registryCenter);
if (converters != null && converters.size() > 0) {
for (Converter c : converters) {
registryCenter.register(c);
}
}
}
private void registerDefaultConverters(ConverterRegistryCenter registryCenter) {
registryCenter.register(new StringConverter());
registryCenter.register(new DateConverter(null));
registryCenter.register(new IntegerConverter());
registryCenter.register(new DoubleConverter());
registryCenter.register(new LongConverter());
registryCenter.register(new FloatConverter());
registryCenter.register(new BooleanConverter());
}
/**
* Write data to a sheet
* Write value to a sheet
*
* @param data Data to be written
* @param sheet Write to this sheet
* @return this current writer
@ -94,23 +141,25 @@ public class ExcelWriter {
/**
* Write data to a sheet
* Write value to a sheet
*
* @param data Data to be written
* @return this current writer
*/
@Deprecated
public ExcelWriter write(List data) {
if (objectClass != null) {
return this.write(data,new Sheet(1,0,objectClass));
}else {
return this.write0(data,new Sheet(1,0,objectClass));
return this.write(data, new Sheet(1, 0, objectClass));
} else {
return this.write0(data, new Sheet(1, 0, objectClass));
}
}
/**
*
* Write data to a sheet
* Write value to a sheet
*
* @param data Data to be written
* @param sheet Write to this sheet
* @return this
@ -121,8 +170,9 @@ public class ExcelWriter {
}
/**
* Write data to a sheet
* @param data Data to be written
* Write value to a sheet
*
* @param data Data to be written
* @param sheet Write to this sheet
* @return this
*/
@ -132,8 +182,9 @@ public class ExcelWriter {
}
/**
* Write data to a sheet
* @param data Data to be written
* Write value to a sheet
*
* @param data Data to be written
* @param sheet Write to this sheet
* @param table Write to this table
* @return this
@ -144,8 +195,9 @@ public class ExcelWriter {
}
/**
* Write data to a sheet
* @param data Data to be written
* Write value to a sheet
*
* @param data Data to be written
* @param sheet Write to this sheet
* @param table Write to this table
* @return this
@ -158,19 +210,17 @@ public class ExcelWriter {
/**
* Merge CellsIndexes are zero-based.
*
* @param firstRow Index of first row
* @param lastRow Index of last row (inclusive), must be equal to or larger than {@code firstRow}
* @param firstCol Index of first column
* @param lastCol Index of last column (inclusive), must be equal to or larger than {@code firstCol}
* @param strategies the merge strategies.
*/
public ExcelWriter merge(int firstRow, int lastRow, int firstCol, int lastCol){
excelBuilder.merge(firstRow,lastRow,firstCol,lastCol);
public ExcelWriter merge(List<MergeStrategy> strategies) {
excelBuilder.merge(strategies);
return this;
}
/**
* Write data to a sheet
* @param data Data to be written
* Write value to a sheet
*
* @param data Data to be written
* @param sheet Write to this sheet
* @param table Write to this table
* @return

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

@ -1,41 +1,85 @@
package com.alibaba.excel.analysis;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.AnalysisEventRegisterCenter;
import com.alibaba.excel.event.OneRowAnalysisFinishEvent;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.util.TypeUtil;
import java.util.ArrayList;
import java.util.Collection;
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.BooleanConverter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.converters.DateConverter;
import com.alibaba.excel.converters.DoubleConverter;
import com.alibaba.excel.converters.FloatConverter;
import com.alibaba.excel.converters.IntegerConverter;
import com.alibaba.excel.converters.LongConverter;
import com.alibaba.excel.converters.StringConverter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
import com.alibaba.excel.event.AnalysisFinishEvent;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import com.alibaba.excel.metadata.Sheet;
/**
* @author jipengfei
*/
public abstract class BaseSaxAnalyser implements AnalysisEventRegisterCenter, ExcelAnalyser {
public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, AnalysisEventRegistryCenter, ExcelAnalyser {
protected AnalysisContext analysisContext;
private LinkedHashMap<String, AnalysisEventListener> listeners = new LinkedHashMap<String, AnalysisEventListener>();
private LinkedHashMap<String, AnalysisEventListener<Object>> listeners =
new LinkedHashMap<String, AnalysisEventListener<Object>>();
private LinkedHashMap<String, Converter> converters = new LinkedHashMap<String, Converter>();
/**
* execute method
*/
protected abstract void execute();
@Override
public void appendLister(String name, AnalysisEventListener listener) {
public void register(String name, AnalysisEventListener<Object> listener) {
if (!listeners.containsKey(name)) {
listeners.put(name, listener);
}
}
@Override
public void register(Converter converter) {
converters.put(converter.getName(), converter);
}
@Override
public void beforeAnalysis() {
registerDefaultConverters();
}
private void registerDefaultConverters() {
StringConverter s = new StringConverter();
converters.put(s.getName(), s);
DateConverter d = new DateConverter(this.analysisContext);
converters.put(d.getName(), d);
IntegerConverter i = new IntegerConverter();
converters.put(i.getName(), i);
DoubleConverter dc = new DoubleConverter();
converters.put(dc.getName(), dc);
LongConverter l = new LongConverter();
converters.put(l.getName(), l);
FloatConverter f = new FloatConverter();
converters.put(f.getName(), f);
BooleanConverter b = new BooleanConverter();
converters.put(b.getName(), b);
}
@Override
public Collection<Converter> getConverters() {
return converters.values();
}
@Override
public void analysis(Sheet sheetParam) {
analysisContext.setCurrentSheet(sheetParam);
execute();
}
@ -44,44 +88,42 @@ public abstract class BaseSaxAnalyser implements AnalysisEventRegisterCenter, Ex
execute();
}
@Override
public AnalysisContext getAnalysisContext() {
return analysisContext;
}
/**
*/
@Override
public void cleanAllListeners() {
listeners = new LinkedHashMap<String, AnalysisEventListener>();
listeners.clear();
}
@Override
public void notifyListeners(OneRowAnalysisFinishEvent event) {
analysisContext.setCurrentRowAnalysisResult(event.getData());
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().getHeadLineMun()) {
if (analysisContext.getCurrentRowNum() <= analysisContext.getCurrentSheet().getHeadLineMun() - 1) {
analysisContext.buildExcelHeadProperty(null,
(List<String>)analysisContext.getCurrentRowAnalysisResult());
buildExcelHeadProperty(null, (List<String>) analysisContext.getCurrentRowAnalysisResult());
}
} else {
List<String> content = converter((List<String>)event.getData());
/** Parsing Analyze the body content **/
analysisContext.setCurrentRowAnalysisResult(content);
if (listeners.size() == 1) {
analysisContext.setCurrentRowAnalysisResult(content);
}
/** notify all event listeners **/
for (Map.Entry<String, AnalysisEventListener> entry : listeners.entrySet()) {
for (Entry<String, AnalysisEventListener<Object>> entry : listeners.entrySet()) {
entry.getValue().invoke(analysisContext.getCurrentRowAnalysisResult(), analysisContext);
}
}
}
private List<String> converter(List<String> data) {
List<String> list = new ArrayList<String>();
if (data != null) {
for (String str : data) {
list.add(TypeUtil.formatFloat(str));
}
}
return list;
}
private void buildExcelHeadProperty(Class<? extends BaseRowModel> clazz, List<String> headOneRow) {
ExcelHeadProperty excelHeadProperty = ExcelHeadProperty
.buildExcelHeadProperty(this.analysisContext.getExcelHeadProperty(), clazz, headOneRow);
this.analysisContext.setExcelHeadProperty(excelHeadProperty);
}
}

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

@ -1,16 +1,19 @@
package com.alibaba.excel.analysis;
import com.alibaba.excel.metadata.Sheet;
import java.util.List;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.Sheet;
/**
* Excel file analyser
*
* @author jipengfei
*/
public interface ExcelAnalyser {
void beforeAnalysis();
/**
* parse one sheet
*
@ -29,5 +32,11 @@ public interface ExcelAnalyser {
* @return all sheets
*/
List<Sheet> getSheets();
/**
* get the analysis context.
* @return analysis context
*/
AnalysisContext getAnalysisContext();
}

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

@ -1,18 +1,21 @@
package com.alibaba.excel.analysis;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
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.ConverterRegistryCenter;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.modelbuild.ModelBuildEventListener;
import com.alibaba.excel.event.ModelBuildEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import java.io.InputStream;
import java.util.List;
/**
* @author jipengfei
*/
@ -23,9 +26,21 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
private BaseSaxAnalyser saxAnalyser;
public ExcelAnalyserImpl(InputStream inputStream, ExcelTypeEnum excelTypeEnum, Object custom,
AnalysisEventListener eventListener, boolean trim) {
AnalysisEventListener<Object> eventListener, boolean trim) {
ConverterRegistryCenter center = new ConverterRegistryCenter() {
@Override
public void register(Converter converter) {
saxAnalyser.register(converter);
}
@Override
public Collection<Converter> getConverters() {
return saxAnalyser.getConverters();
}
};
analysisContext = new AnalysisContextImpl(inputStream, excelTypeEnum, custom,
eventListener, trim);
eventListener, center, trim);
this.saxAnalyser = getSaxAnalyser();
}
private BaseSaxAnalyser getSaxAnalyser() {
@ -60,36 +75,40 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
}
return this.saxAnalyser;
}
@Override
public void analysis(Sheet sheetParam) {
analysisContext.setCurrentSheet(sheetParam);
analysis();
}
@Override
public AnalysisContext getAnalysisContext() {
return analysisContext;
}
@Override
public void analysis() {
BaseSaxAnalyser saxAnalyser = getSaxAnalyser();
appendListeners(saxAnalyser);
saxAnalyser.execute();
analysisContext.getEventListener().doAfterAllAnalysed(analysisContext);
}
@Override
public List<Sheet> getSheets() {
BaseSaxAnalyser saxAnalyser = getSaxAnalyser();
saxAnalyser.cleanAllListeners();
return saxAnalyser.getSheets();
return this.saxAnalyser.getSheets();
}
private void appendListeners(BaseSaxAnalyser saxAnalyser) {
private void registerListeners(BaseSaxAnalyser saxAnalyser) {
saxAnalyser.cleanAllListeners();
if (analysisContext.getCurrentSheet() != null && analysisContext.getCurrentSheet().getClazz() != null) {
saxAnalyser.appendLister("model_build_listener", new ModelBuildEventListener());
saxAnalyser.register("model_build_listener", new ModelBuildEventListener(this.saxAnalyser.getConverters()));
}
if (analysisContext.getEventListener() != null) {
saxAnalyser.appendLister("user_define_listener", analysisContext.getEventListener());
saxAnalyser.register("user_define_listener", analysisContext.getEventListener());
}
}
@Override
public void beforeAnalysis() {
BaseSaxAnalyser saxAnalyser = getSaxAnalyser();
registerListeners(saxAnalyser);
}
}

27
src/main/java/com/alibaba/excel/analysis/v03/AbstractXlsRecordHandler.java

@ -0,0 +1,27 @@
package com.alibaba.excel.analysis.v03;
public abstract class AbstractXlsRecordHandler implements XlsRecordHandler {
protected int row = -1;
protected int column = -1;
protected String value = null;
@Override
public int getRow() {
return row;
}
@Override
public int getColumn() {
return column;
}
@Override
public String getValue() {
return value;
}
@Override
public int compareTo(XlsRecordHandler o) {
return this.getOrder() - o.getOrder();
}
}

13
src/main/java/com/alibaba/excel/analysis/v03/XlsRecordHandler.java

@ -0,0 +1,13 @@
package com.alibaba.excel.analysis.v03;
import org.apache.poi.hssf.record.Record;
public interface XlsRecordHandler extends Comparable<XlsRecordHandler> {
boolean support(Record record);
void init();
void processRecord(Record record);
int getRow();
int getColumn();
String getValue();
int getOrder();
}

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

@ -1,20 +1,21 @@
package com.alibaba.excel.analysis.v03;
import com.alibaba.excel.analysis.BaseSaxAnalyser;
import com.alibaba.excel.analysis.v03.handlers.*;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.OneRowAnalysisFinishEvent;
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.eventusermodel.dummyrecord.MissingCellDummyRecord;
import org.apache.poi.hssf.model.HSSFFormulaParser;
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;
/**
@ -26,15 +27,23 @@ import java.util.List;
* @author jipengfei
*/
public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
private boolean analyAllSheet = false;
private boolean outputFormulaValues = true;
private POIFSFileSystem fs;
private int lastRowNumber;
private int lastColumnNumber;
/**
* For parsing Formulas
*/
private EventWorkbookBuilder.SheetRecordCollectingListener workbookBuildingListener;
private FormatTrackingHSSFListener formatListener;
private List<String> records;
private boolean notAllEmpty = false;
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>();
if (analysisContext.getCurrentSheet() == null) {
this.analyAllSheet = true;
}
context.setCurrentRowNum(0);
this.fs = new POIFSFileSystem(analysisContext.getInputStream());
@ -42,23 +51,25 @@ public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
@Override
public List<Sheet> getSheets() {
execute();
return sheets;
}
@Override
public void execute() {
init();
MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);
formatListener = new FormatTrackingHSSFListener(listener);
workbookBuildingListener = new EventWorkbookBuilder.SheetRecordCollectingListener(formatListener);
if (workbookBuildingListener != null && stubWorkbook == null) {
stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
}
init();
HSSFEventFactory factory = new HSSFEventFactory();
HSSFRequest request = new HSSFRequest();
if (outputFormulaValues) {
request.addListenerForAllRecords(formatListener);
} else {
workbookBuildingListener = new EventWorkbookBuilder.SheetRecordCollectingListener(formatListener);
request.addListenerForAllRecords(workbookBuildingListener);
}
@ -72,223 +83,42 @@ public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
private void init() {
lastRowNumber = 0;
lastColumnNumber = 0;
nextRow = 0;
nextColumn = 0;
sheetIndex = 0;
records = new ArrayList<String>();
notAllEmpty = false;
orderedBSRs = null;
boundSheetRecords = new ArrayList<BoundSheetRecord>();
sheets = new ArrayList<Sheet>();
if (analysisContext.getCurrentSheet() == null) {
this.analyAllSheet = true;
} else {
this.analyAllSheet = false;
}
buildXlsRecordHandlers();
}
private POIFSFileSystem fs;
private int lastRowNumber;
private int lastColumnNumber;
/**
* Should we output the formula, or the value it has?
*/
private boolean outputFormulaValues = true;
/**
* For parsing Formulas
*/
private EventWorkbookBuilder.SheetRecordCollectingListener workbookBuildingListener;
private HSSFWorkbook stubWorkbook;
private SSTRecord sstRecord;
private FormatTrackingHSSFListener formatListener;
/**
* So we known which sheet we're on
*/
private int nextRow;
private int nextColumn;
private boolean outputNextStringRecord;
/**
* Main HSSFListener method, processes events, and outputs the CSV as the file is processed.
*/
private int sheetIndex;
private List<String> records;
private boolean notAllEmpty = false;
private BoundSheetRecord[] orderedBSRs;
private List<BoundSheetRecord> boundSheetRecords = new ArrayList<BoundSheetRecord>();
private List<Sheet> sheets = new ArrayList<Sheet>();
public void processRecord(Record record) {
int thisRow = -1;
int thisColumn = -1;
String thisStr = null;
switch (record.getSid()) {
case BoundSheetRecord.sid:
boundSheetRecords.add((BoundSheetRecord)record);
break;
case BOFRecord.sid:
BOFRecord br = (BOFRecord)record;
if (br.getType() == BOFRecord.TYPE_WORKSHEET) {
// Create sub workbook if required
if (workbookBuildingListener != null && stubWorkbook == null) {
stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
}
if (orderedBSRs == null) {
orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
}
sheetIndex++;
Sheet sheet = new Sheet(sheetIndex, 0);
sheet.setSheetName(orderedBSRs[sheetIndex - 1].getSheetname());
sheets.add(sheet);
if (this.analyAllSheet) {
analysisContext.setCurrentSheet(sheet);
}
}
break;
case SSTRecord.sid:
sstRecord = (SSTRecord)record;
break;
case BlankRecord.sid:
BlankRecord brec = (BlankRecord)record;
thisRow = brec.getRow();
thisColumn = brec.getColumn();
thisStr = "";
break;
case BoolErrRecord.sid:
BoolErrRecord berec = (BoolErrRecord)record;
thisRow = berec.getRow();
thisColumn = berec.getColumn();
thisStr = "";
break;
case FormulaRecord.sid:
FormulaRecord frec = (FormulaRecord)record;
thisRow = frec.getRow();
thisColumn = frec.getColumn();
if (outputFormulaValues) {
if (Double.isNaN(frec.getValue())) {
// Formula result is a string
// This is stored in the next record
outputNextStringRecord = true;
nextRow = frec.getRow();
nextColumn = frec.getColumn();
} else {
thisStr = formatListener.formatNumberDateCell(frec);
}
} else {
thisStr = HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression());
}
break;
case StringRecord.sid:
if (outputNextStringRecord) {
// String for formula
StringRecord srec = (StringRecord)record;
thisStr = srec.getString();
thisRow = nextRow;
thisColumn = nextColumn;
outputNextStringRecord = false;
}
break;
case LabelRecord.sid:
LabelRecord lrec = (LabelRecord)record;
thisRow = lrec.getRow();
thisColumn = lrec.getColumn();
thisStr = lrec.getValue();
break;
case LabelSSTRecord.sid:
LabelSSTRecord lsrec = (LabelSSTRecord)record;
thisRow = lsrec.getRow();
thisColumn = lsrec.getColumn();
if (sstRecord == null) {
thisStr = "";
} else {
thisStr = sstRecord.getString(lsrec.getSSTIndex()).toString();
}
break;
case NoteRecord.sid:
NoteRecord nrec = (NoteRecord)record;
thisRow = nrec.getRow();
thisColumn = nrec.getColumn();
// TODO: Find object to match nrec.getShapeId()
thisStr = "(TODO)";
for(XlsRecordHandler handler : this.recordHandlers) {
if (handler.support(record)) {
handler.processRecord(record);
thisRow = handler.getRow();
thisColumn = handler.getColumn();
thisStr = handler.getValue();
break;
case NumberRecord.sid:
NumberRecord numrec = (NumberRecord)record;
thisRow = numrec.getRow();
thisColumn = numrec.getColumn();
// Format
thisStr = formatListener.formatNumberDateCell(numrec);
break;
case RKRecord.sid:
RKRecord rkrec = (RKRecord)record;
thisRow = rkrec.getRow();
thisColumn = rkrec.getColumn();
thisStr = "";
break;
default:
break;
}
// Handle new row
if (thisRow != -1 && thisRow != lastRowNumber) {
lastColumnNumber = -1;
}
// Handle missing column
if (record instanceof MissingCellDummyRecord) {
MissingCellDummyRecord mc = (MissingCellDummyRecord)record;
thisRow = mc.getRow();
thisColumn = mc.getColumn();
thisStr = "";
}
}
// If we got something to print out, do so
if (thisStr != null) {
if (analysisContext.trim()) {
thisStr = thisStr.trim();
}
if (!"".equals(thisStr)) {
notAllEmpty = true;
}
// }
records.add(thisStr);
}
// Handle new row
if (thisRow != -1 && thisRow != lastRowNumber) {
lastColumnNumber = -1;
}
// Update column and row count
if (thisRow > -1) {
lastRowNumber = thisRow;
@ -297,22 +127,43 @@ public class XlsSaxAnalyser extends BaseSaxAnalyser implements HSSFListener {
lastColumnNumber = thisColumn;
}
processLastCellOfRow(record);
}
private void processLastCellOfRow(Record record) {
// Handle end of row
if (record instanceof LastCellOfRowDummyRecord) {
thisRow = ((LastCellOfRowDummyRecord)record).getRow();
int row = ((LastCellOfRowDummyRecord)record).getRow();
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
analysisContext.setCurrentRowNum(thisRow);
Sheet sheet = analysisContext.getCurrentSheet();
if ((sheet == null || sheet.getSheetNo() == sheetIndex) && notAllEmpty) {
notifyListeners(new OneRowAnalysisFinishEvent(records));
analysisContext.setCurrentRowNum(row);
if (notAllEmpty) {
notify(new EachRowAnalysisFinishEvent(new ArrayList<String>(records)));
}
records.clear();
lastColumnNumber = -1;
notAllEmpty = false;
}
}
private void buildXlsRecordHandlers() {
if (CollectionUtils.isEmpty(recordHandlers)) {
recordHandlers.add(new BlankOrErrorRecordHandler());
recordHandlers.add(new BOFRecordHandler(workbookBuildingListener, analysisContext, sheets));
recordHandlers.add(new FormulaRecordHandler(stubWorkbook, formatListener));
recordHandlers.add(new LabelRecordHandler());
recordHandlers.add(new NoteRecordHandler());
recordHandlers.add(new NumberRecordHandler(formatListener));
recordHandlers.add(new RKRecordHandler());
recordHandlers.add(new SSTRecordHandler());
recordHandlers.add(new MissingCellDummyRecordHandler());
Collections.sort(recordHandlers);
}
for(XlsRecordHandler x : recordHandlers) {
x.init();
}
}
}

71
src/main/java/com/alibaba/excel/analysis/v03/handlers/BOFRecordHandler.java

@ -0,0 +1,71 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import com.alibaba.excel.analysis.v03.XlsRecordHandler;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.Sheet;
import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.util.ArrayList;
import java.util.List;
public class BOFRecordHandler extends AbstractXlsRecordHandler {
private List<BoundSheetRecord> boundSheetRecords = new ArrayList<BoundSheetRecord>();
private BoundSheetRecord[] orderedBSRs;
private int sheetIndex;
private List<Sheet> sheets;
private AnalysisContext context;
private boolean analyAllSheet;
private EventWorkbookBuilder.SheetRecordCollectingListener workbookBuildingListener;
public BOFRecordHandler(EventWorkbookBuilder.SheetRecordCollectingListener workbookBuildingListener, AnalysisContext context, List<Sheet> sheets) {
this.context = context;
this.workbookBuildingListener = workbookBuildingListener;
this.sheets = sheets;
}
@Override
public boolean support(Record record) {
return BoundSheetRecord.sid == record.getSid() || BOFRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
if (record.getSid() == BoundSheetRecord.sid) {
boundSheetRecords.add((BoundSheetRecord)record);
} else if (record.getSid() == BOFRecord.sid) {
BOFRecord br = (BOFRecord)record;
if (br.getType() == BOFRecord.TYPE_WORKSHEET) {
if (orderedBSRs == null) {
orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
}
sheetIndex++;
Sheet sheet = new Sheet(sheetIndex, 0);
sheet.setSheetName(orderedBSRs[sheetIndex - 1].getSheetname());
sheets.add(sheet);
if (this.analyAllSheet) {
context.setCurrentSheet(sheet);
}
}
}
}
@Override
public void init() {
if (context.getCurrentSheet() == null) {
this.analyAllSheet = true;
}
sheetIndex = 0;
orderedBSRs = null;
boundSheetRecords.clear();
sheets.clear();
}
@Override
public int getOrder() {
return 0;
}
}

37
src/main/java/com/alibaba/excel/analysis/v03/handlers/BlankOrErrorRecordHandler.java

@ -0,0 +1,37 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.record.*;
public class BlankOrErrorRecordHandler extends AbstractXlsRecordHandler {
@Override
public boolean support(Record record) {
return BlankRecord.sid == record.getSid() || BoolErrRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
if (record.getSid() == BlankRecord.sid) {
BlankRecord br = (BlankRecord)record;
this.row = br.getRow();
this.column = br.getColumn();
this.value = "";
} else if (record.getSid() == BoolErrRecord.sid) {
BoolErrRecord ber = (BoolErrRecord)record;
this.row = ber.getRow();
this.column = ber.getColumn();
this.value = "";
}
}
@Override
public void init() {
}
@Override
public int getOrder() {
return 0;
}
}

71
src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java

@ -0,0 +1,71 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class FormulaRecordHandler extends AbstractXlsRecordHandler {
private int nextRow;
private int nextColumn;
/**
* Should we output the formula, or the value it has?
*/
private boolean outputFormulaValues = true;
private boolean outputNextStringRecord;
private FormatTrackingHSSFListener formatListener;
private HSSFWorkbook stubWorkbook;
public FormulaRecordHandler(HSSFWorkbook stubWorkbook, FormatTrackingHSSFListener formatListener) {
this.stubWorkbook = stubWorkbook;
this.formatListener = formatListener;
}
@Override
public boolean support(Record record) {
return FormulaRecord.sid == record.getSid() || StringRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
if (record.getSid() == FormulaRecord.sid) {
FormulaRecord frec = (FormulaRecord)record;
this.row = frec.getRow();
this.column = frec.getColumn();
if (outputFormulaValues) {
if (Double.isNaN(frec.getValue())) {
// Formula result is a string
// This is stored in the next record
outputNextStringRecord = true;
nextRow = frec.getRow();
nextColumn = frec.getColumn();
} else {
this.value = formatListener.formatNumberDateCell(frec);
}
} else {
this.value = HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression());
}
} else if (record.getSid() == StringRecord.sid) {
if (outputNextStringRecord) {
// String for formula
StringRecord srec = (StringRecord)record;
this.value = srec.getString();
this.row = nextRow;
this.column = nextColumn;
outputNextStringRecord = false;
}
}
}
@Override
public void init() {
this.nextRow = 0;
this.nextColumn = 0;
}
@Override
public int getOrder() {
return 0;
}
}

30
src/main/java/com/alibaba/excel/analysis/v03/handlers/LabelRecordHandler.java

@ -0,0 +1,30 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.record.LabelRecord;
import org.apache.poi.hssf.record.Record;
public class LabelRecordHandler extends AbstractXlsRecordHandler {
@Override
public boolean support(Record record) {
return LabelRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
LabelRecord lrec = (LabelRecord)record;
this.row = lrec.getRow();
this.column = lrec.getColumn();
this.value = lrec.getValue();
}
@Override
public void init() {
}
@Override
public int getOrder() {
return 0;
}
}

30
src/main/java/com/alibaba/excel/analysis/v03/handlers/MissingCellDummyRecordHandler.java

@ -0,0 +1,30 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
import org.apache.poi.hssf.record.Record;
public class MissingCellDummyRecordHandler extends AbstractXlsRecordHandler {
@Override
public boolean support(Record record) {
return record instanceof MissingCellDummyRecord;
}
@Override
public void init() {
}
@Override
public void processRecord(Record record) {
MissingCellDummyRecord mcdr = (MissingCellDummyRecord)record;
this.row = mcdr.getRow();
this.column = mcdr.getColumn();
this.value = "";
}
@Override
public int getOrder() {
return 1;
}
}

32
src/main/java/com/alibaba/excel/analysis/v03/handlers/NoteRecordHandler.java

@ -0,0 +1,32 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.Record;
public class NoteRecordHandler extends AbstractXlsRecordHandler {
@Override
public boolean support(Record record) {
return NoteRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
NoteRecord nrec = (NoteRecord)record;
this.row = nrec.getRow();
this.column = nrec.getColumn();
// TODO: Find object to match nrec.getShapeId()
this.value = "(TODO)";
}
@Override
public void init() {
}
@Override
public int getOrder() {
return 0;
}
}

36
src/main/java/com/alibaba/excel/analysis/v03/handlers/NumberRecordHandler.java

@ -0,0 +1,36 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record;
public class NumberRecordHandler extends AbstractXlsRecordHandler {
private FormatTrackingHSSFListener formatListener;
public NumberRecordHandler(FormatTrackingHSSFListener formatListener) {
this.formatListener = formatListener;
}
@Override
public boolean support(Record record) {
return NumberRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
NumberRecord numrec = (NumberRecord)record;
this.row = numrec.getRow();
this.column = numrec.getColumn();
// Format
this.value = formatListener.formatNumberDateCell(numrec);
}
@Override
public void init() {
}
@Override
public int getOrder() {
return 0;
}
}

31
src/main/java/com/alibaba/excel/analysis/v03/handlers/RKRecordHandler.java

@ -0,0 +1,31 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.record.RKRecord;
import org.apache.poi.hssf.record.Record;
public class RKRecordHandler extends AbstractXlsRecordHandler {
@Override
public boolean support(Record record) {
return RKRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
RKRecord rkrec = (RKRecord)record;
this.row = rkrec.getRow();
this.row = rkrec.getColumn();
this.value = "";
}
@Override
public void init() {
}
@Override
public int getOrder() {
return 0;
}
}

39
src/main/java/com/alibaba/excel/analysis/v03/handlers/SSTRecordHandler.java

@ -0,0 +1,39 @@
package com.alibaba.excel.analysis.v03.handlers;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
import org.apache.poi.hssf.record.*;
public class SSTRecordHandler extends AbstractXlsRecordHandler {
private SSTRecord sstRecord;
@Override
public boolean support(Record record) {
return SSTRecord.sid == record.getSid() || LabelSSTRecord.sid == record.getSid();
}
@Override
public void processRecord(Record record) {
if (record.getSid() == SSTRecord.sid) {
sstRecord = (SSTRecord)record;
} else if (record.getSid() == LabelSSTRecord.sid) {
LabelSSTRecord lsrec = (LabelSSTRecord)record;
this.row = lsrec.getRow();
this.column = lsrec.getColumn();
if (sstRecord == null) {
this.value = "";
} else {
this.value = sstRecord.getString(lsrec.getSSTIndex()).toString();
}
}
}
@Override
public void init() {
}
@Override
public int getOrder() {
return 0;
}
}

11
src/main/java/com/alibaba/excel/analysis/v07/XlsxCellHandler.java

@ -0,0 +1,11 @@
package com.alibaba.excel.analysis.v07;
import org.xml.sax.Attributes;
public interface XlsxCellHandler {
boolean support(String name);
void startHandle(String name, Attributes attributes);
void endHandle(String name);
}

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

@ -0,0 +1,29 @@
package com.alibaba.excel.analysis.v07;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.xssf.model.SharedStringsTable;
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.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
public class XlsxHandlerFactory {
public static List<XlsxCellHandler> buildCellHandlers(AnalysisContext analysisContext,
AnalysisEventRegistryCenter registerCenter, SharedStringsTable sst) {
List<XlsxCellHandler> result = new ArrayList<XlsxCellHandler>();
result.add(new CountRowCellHandler(analysisContext));
DefaultCellHandler defaultCellHandler = buildXlsxRowResultHandler(analysisContext, registerCenter, sst);
result.add(defaultCellHandler);
result.add(new ProcessResultCellHandler(registerCenter, defaultCellHandler));
return result;
}
private static DefaultCellHandler buildXlsxRowResultHandler(AnalysisContext analysisContext,
AnalysisEventRegistryCenter registerCenter, SharedStringsTable sst) {
return new DefaultCellHandler(analysisContext, registerCenter, sst);
}
}

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

@ -1,20 +1,14 @@
package com.alibaba.excel.analysis.v07;
import com.alibaba.excel.annotation.FieldType;
import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventRegisterCenter;
import com.alibaba.excel.event.OneRowAnalysisFinishEvent;
import com.alibaba.excel.util.PositionUtils;
import java.util.List;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.Arrays;
import static com.alibaba.excel.constant.ExcelXmlConstants.*;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
/**
*
@ -22,117 +16,43 @@ import static com.alibaba.excel.constant.ExcelXmlConstants.*;
*/
public class XlsxRowHandler extends DefaultHandler {
private String currentCellIndex;
private FieldType currentCellType;
private int curRow;
private int curCol;
private String[] curRowContent = new String[20];
private String currentCellValue;
private SharedStringsTable sst;
private AnalysisContext analysisContext;
private AnalysisEventRegisterCenter registerCenter;
public XlsxRowHandler(AnalysisEventRegisterCenter registerCenter, SharedStringsTable sst,
AnalysisContext analysisContext) {
this.registerCenter = registerCenter;
this.analysisContext = analysisContext;
this.sst = sst;
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
setTotalRowCount(name, attributes);
startCell(name, attributes);
startCellValue(name);
private List<XlsxCellHandler> cellHandlers;
private XlsxRowResultHolder rowResultHolder;
}
private void startCellValue(String name) {
if (name.equals(CELL_VALUE_TAG) || name.equals(CELL_VALUE_TAG_1)) {
// initialize current cell value
currentCellValue = "";
}
}
private void startCell(String name, Attributes attributes) {
if (ExcelXmlConstants.CELL_TAG.equals(name)) {
currentCellIndex = attributes.getValue(ExcelXmlConstants.POSITION);
int nextRow = PositionUtils.getRow(currentCellIndex);
if (nextRow > curRow) {
curRow = nextRow;
// endRow(ROW_TAG);
}
analysisContext.setCurrentRowNum(curRow);
curCol = PositionUtils.getCol(currentCellIndex);
String cellType = attributes.getValue("t");
currentCellType = FieldType.EMPTY;
if (cellType != null && cellType.equals("s")) {
currentCellType = FieldType.STRING;
public XlsxRowHandler(AnalysisEventRegistryCenter registerCenter, SharedStringsTable sst,
AnalysisContext analysisContext) {
this.cellHandlers = XlsxHandlerFactory.buildCellHandlers(analysisContext, registerCenter, sst);
for (XlsxCellHandler cellHandler : cellHandlers) {
if (cellHandler instanceof XlsxRowResultHolder) {
this.rowResultHolder = (XlsxRowResultHolder) cellHandler;
break;
}
}
}
private void endCellValue(String name) throws SAXException {
// ensure size
if (curCol >= curRowContent.length) {
curRowContent = Arrays.copyOf(curRowContent, (int)(curCol * 1.5));
}
if (CELL_VALUE_TAG.equals(name)) {
switch (currentCellType) {
case STRING:
int idx = Integer.parseInt(currentCellValue);
currentCellValue = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
currentCellType = FieldType.EMPTY;
break;
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
for (XlsxCellHandler cellHandler : cellHandlers) {
if (cellHandler.support(name)) {
cellHandler.startHandle(name, attributes);
}
curRowContent[curCol] = currentCellValue;
} else if (CELL_VALUE_TAG_1.equals(name)) {
curRowContent[curCol] = currentCellValue;
}
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
endRow(name);
endCellValue(name);
for (XlsxCellHandler cellHandler : cellHandlers) {
if (cellHandler.support(name)) {
cellHandler.endHandle(name);
}
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
currentCellValue += new String(ch, start, length);
}
private void setTotalRowCount(String name, Attributes attributes) {
if (DIMENSION.equals(name)) {
String d = attributes.getValue(DIMENSION_REF);
String totalStr = d.substring(d.indexOf(":") + 1, d.length());
String c = totalStr.toUpperCase().replaceAll("[A-Z]", "");
analysisContext.setTotalCount(Integer.parseInt(c));
if (rowResultHolder != null) {
rowResultHolder.appendCurrentCellValue(new String(ch, start, length));
}
}
private void endRow(String name) {
if (name.equals(ROW_TAG)) {
registerCenter.notifyListeners(new OneRowAnalysisFinishEvent(curRowContent,curCol));
curRowContent = new String[20];
}
}
}

11
src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java

@ -0,0 +1,11 @@
package com.alibaba.excel.analysis.v07;
public interface XlsxRowResultHolder {
void clearResult();
void appendCurrentCellValue(String currentCellValue);
String[] getCurRowContent();
int getColumnSize();
}

36
src/main/java/com/alibaba/excel/analysis/v07/handlers/CountRowCellHandler.java

@ -0,0 +1,36 @@
package com.alibaba.excel.analysis.v07.handlers;
import static com.alibaba.excel.constant.ExcelXmlConstants.DIMENSION;
import static com.alibaba.excel.constant.ExcelXmlConstants.DIMENSION_REF;
import org.xml.sax.Attributes;
import com.alibaba.excel.analysis.v07.XlsxCellHandler;
import com.alibaba.excel.context.AnalysisContext;
public class CountRowCellHandler implements XlsxCellHandler {
private final AnalysisContext analysisContext;
public CountRowCellHandler(AnalysisContext analysisContext) {
this.analysisContext = analysisContext;
}
@Override
public boolean support(String name) {
return DIMENSION.equals(name);
}
@Override
public void startHandle(String name, Attributes attributes) {
String d = attributes.getValue(DIMENSION_REF);
String totalStr = d.substring(d.indexOf(":") + 1, d.length());
String c = totalStr.toUpperCase().replaceAll("[A-Z]", "");
analysisContext.setTotalCount(Integer.parseInt(c));
}
@Override
public void endHandle(String name) {
}
}

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

@ -0,0 +1,121 @@
package com.alibaba.excel.analysis.v07.handlers;
import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TAG;
import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_TAG;
import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TAG_1;
import java.util.Arrays;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import com.alibaba.excel.analysis.v07.XlsxCellHandler;
import com.alibaba.excel.analysis.v07.XlsxRowResultHolder;
import com.alibaba.excel.annotation.FieldType;
import com.alibaba.excel.constant.ExcelXmlConstants;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
import com.alibaba.excel.util.PositionUtils;
public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder {
private String currentCellIndex;
private FieldType currentCellType;
private int curRow;
private int curCol;
private String[] curRowContent = new String[20];
private String currentCellValue;
private final AnalysisContext analysisContext;
private final AnalysisEventRegistryCenter registerCenter;
private final SharedStringsTable sst;
public DefaultCellHandler(AnalysisContext analysisContext, AnalysisEventRegistryCenter registerCenter, SharedStringsTable sst) {
this.analysisContext = analysisContext;
this.registerCenter = registerCenter;
this.sst = sst;
}
@Override
public void clearResult() {
curRowContent = new String[20];
}
@Override
public boolean support(String name) {
return CELL_VALUE_TAG.equals(name) || CELL_VALUE_TAG_1.equals(name) || CELL_TAG.equals(name);
}
@Override
public void startHandle(String name, Attributes attributes) {
if (CELL_TAG.equals(name)) {
currentCellIndex = attributes.getValue(ExcelXmlConstants.POSITION);
int nextRow = PositionUtils.getRow(currentCellIndex);
if (nextRow > curRow) {
curRow = nextRow;
// endRow(ROW_TAG);
}
analysisContext.setCurrentRowNum(curRow);
curCol = PositionUtils.getCol(currentCellIndex);
String cellType = attributes.getValue("t");
currentCellType = FieldType.EMPTY;
if (cellType != null && cellType.equals("s")) {
currentCellType = FieldType.STRING;
}
}
if (name.equals(CELL_VALUE_TAG) || name.equals(CELL_VALUE_TAG_1)) {
// initialize current cell value
currentCellValue = "";
}
}
@Override
public void endHandle(String name) {
ensureSize();
if (CELL_VALUE_TAG.equals(name)) {
switch (currentCellType) {
case STRING:
int idx = Integer.parseInt(currentCellValue);
currentCellValue = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
currentCellType = FieldType.EMPTY;
break;
}
curRowContent[curCol] = currentCellValue;
} else if (CELL_VALUE_TAG_1.equals(name)) {
curRowContent[curCol] = currentCellValue;
}
}
private void ensureSize() {
// try to size
if (curCol >= curRowContent.length) {
curRowContent = Arrays.copyOf(curRowContent, (int) (curCol * 1.5));
}
}
@Override
public void appendCurrentCellValue(String currentCellValue) {
this.currentCellValue += currentCellValue;
}
@Override
public String[] getCurRowContent() {
return this.curRowContent;
}
@Override
public int getColumnSize() {
return this.curCol;
}
}

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

@ -0,0 +1,37 @@
package com.alibaba.excel.analysis.v07.handlers;
import org.xml.sax.Attributes;
import static com.alibaba.excel.constant.ExcelXmlConstants.ROW_TAG;
import com.alibaba.excel.analysis.v07.XlsxCellHandler;
import com.alibaba.excel.analysis.v07.XlsxRowResultHolder;
import com.alibaba.excel.event.AnalysisEventRegistryCenter;
import com.alibaba.excel.event.EachRowAnalysisFinishEvent;
public class ProcessResultCellHandler implements XlsxCellHandler {
private AnalysisEventRegistryCenter registerCenter;
private XlsxRowResultHolder rowResultHandler;
public ProcessResultCellHandler(AnalysisEventRegistryCenter registerCenter,
XlsxRowResultHolder rowResultHandler) {
this.registerCenter = registerCenter;
this.rowResultHandler = rowResultHandler;
}
@Override
public boolean support(String name) {
return ROW_TAG.equals(name);
}
@Override
public void startHandle(String name, Attributes attributes) {
}
@Override
public void endHandle(String name) {
registerCenter.notify(new EachRowAnalysisFinishEvent(rowResultHandler.getCurRowContent(),
rowResultHandler.getColumnSize()));
rowResultHandler.clearResult();
}
}

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

@ -1,14 +1,13 @@
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.BaseRowModel;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import java.io.InputStream;
import java.util.List;
/**
*
* A context is the main anchorage point of a excel reader.
@ -52,8 +51,13 @@ public interface AnalysisContext {
* custom listener
* @return listener
*/
AnalysisEventListener getEventListener();
AnalysisEventListener<Object> getEventListener();
/**
* get the converter registry center.
* @return converter registry center.
*/
ConverterRegistryCenter getConverterRegistryCenter();
/**
* get current row
* @return
@ -87,11 +91,10 @@ public interface AnalysisContext {
ExcelHeadProperty getExcelHeadProperty();
/**
*
* @param clazz
* @param headOneRow
* set the excel head property
* @param excelHeadProperty the excel property to set.
*/
void buildExcelHeadProperty(Class<? extends BaseRowModel> clazz, List<String> headOneRow);
void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty);
/**
*

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

@ -1,16 +1,14 @@
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.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author jipengfei
@ -25,7 +23,7 @@ public class AnalysisContextImpl implements AnalysisContext {
private InputStream inputStream;
private AnalysisEventListener eventListener;
private AnalysisEventListener<Object> eventListener;
private Integer currentRowNum;
@ -36,6 +34,8 @@ public class AnalysisContextImpl implements AnalysisContext {
private boolean trim;
private boolean use1904WindowDate = false;
private ConverterRegistryCenter converterRegistryCenter;
@Override
public void setUse1904WindowDate(boolean use1904WindowDate) {
@ -65,20 +65,22 @@ public class AnalysisContextImpl implements AnalysisContext {
private Object currentRowAnalysisResult;
public AnalysisContextImpl(InputStream inputStream, ExcelTypeEnum excelTypeEnum, Object custom,
AnalysisEventListener listener, boolean trim) {
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) {
buildExcelHeadProperty(currentSheet.getClazz(), null);
ExcelHeadProperty.buildExcelHeadProperty(this.excelHeadProperty, currentSheet.getClazz(), null);
}
}
@ -122,11 +124,11 @@ public class AnalysisContextImpl implements AnalysisContext {
}
@Override
public AnalysisEventListener getEventListener() {
public AnalysisEventListener<Object> getEventListener() {
return eventListener;
}
public void setEventListener(AnalysisEventListener eventListener) {
public void setEventListener(AnalysisEventListener<Object> eventListener) {
this.eventListener = eventListener;
}
@ -154,19 +156,20 @@ public class AnalysisContextImpl implements AnalysisContext {
public ExcelHeadProperty getExcelHeadProperty() {
return this.excelHeadProperty;
}
@Override
public void buildExcelHeadProperty(Class<? extends BaseRowModel> clazz, List<String> headOneRow) {
if (this.excelHeadProperty == null && (clazz != null || headOneRow != null)) {
this.excelHeadProperty = new ExcelHeadProperty(clazz, new ArrayList<List<String>>());
}
if (this.excelHeadProperty.getHead() == null && headOneRow != null) {
this.excelHeadProperty.appendOneRow(headOneRow);
}
public void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty) {
this.excelHeadProperty = excelHeadProperty;
}
@Override
public boolean trim() {
return this.trim;
}
@Override
public ConverterRegistryCenter getConverterRegistryCenter() {
return converterRegistryCenter;
}
}

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

@ -1,293 +1,35 @@
package com.alibaba.excel.context;
import com.alibaba.excel.event.WriteHandler;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StyleUtil;
import com.alibaba.excel.util.WorkBookUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.alibaba.excel.util.StyleUtil.buildSheetStyle;
/**
* A context is the main anchorage point of a excel writer.
*
* @author jipengfei
*/
public class WriteContext {
/***
* The sheet currently written
*/
private Sheet currentSheet;
/**
* current param
*/
private com.alibaba.excel.metadata.Sheet currentSheetParam;
/**
* The sheet currently written's name
*/
private String currentSheetName;
/**
*
*/
private Table currentTable;
/**
* Excel type
*/
private ExcelTypeEnum excelType;
/**
* POI Workbook
*/
private Workbook workbook;
/**
* Final output stream
*/
private OutputStream outputStream;
/**
* Written form collection
*/
private Map<Integer, Table> tableMap = new ConcurrentHashMap<Integer, Table>();
/**
* Cell default style
*/
private CellStyle defaultCellStyle;
/**
* Current table head style
*/
private CellStyle currentHeadCellStyle;
/**
* Current table content style
*/
private CellStyle currentContentCellStyle;
/**
* the header attribute of excel
*/
private ExcelHeadProperty excelHeadProperty;
private boolean needHead = Boolean.TRUE;
private WriteHandler afterWriteHandler;
public WriteHandler getAfterWriteHandler() {
return afterWriteHandler;
}
public WriteContext(InputStream templateInputStream, OutputStream out, ExcelTypeEnum excelType,
boolean needHead, WriteHandler afterWriteHandler) throws IOException {
this.needHead = needHead;
this.outputStream = out;
this.afterWriteHandler = afterWriteHandler;
this.workbook = WorkBookUtil.createWorkBook(templateInputStream, excelType);
this.defaultCellStyle = StyleUtil.buildDefaultCellStyle(this.workbook);
}
/**
* @param sheet
*/
public void currentSheet(com.alibaba.excel.metadata.Sheet sheet) {
if (null == currentSheetParam || currentSheetParam.getSheetNo() != sheet.getSheetNo()) {
cleanCurrentSheet();
currentSheetParam = sheet;
try {
this.currentSheet = workbook.getSheetAt(sheet.getSheetNo() - 1);
} catch (Exception e) {
this.currentSheet = WorkBookUtil.createSheet(workbook, sheet);
if (null != afterWriteHandler) {
this.afterWriteHandler.sheet(sheet.getSheetNo(), currentSheet);
}
}
buildSheetStyle(currentSheet, sheet.getColumnWidthMap());
/** **/
this.initCurrentSheet(sheet);
}
}
private void initCurrentSheet(com.alibaba.excel.metadata.Sheet sheet) {
/** **/
initExcelHeadProperty(sheet.getHead(), sheet.getClazz());
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
initTableStyle(sheet.getTableStyle());
initTableHead();
}
private void cleanCurrentSheet() {
this.currentSheet = null;
this.currentSheetParam = null;
this.excelHeadProperty = null;
this.currentHeadCellStyle = null;
this.currentContentCellStyle = null;
this.currentTable = null;
}
/**
* init excel header
*
* @param head
* @param clazz
*/
private void initExcelHeadProperty(List<List<String>> head, Class<? extends BaseRowModel> clazz) {
if (head != null || clazz != null) { this.excelHeadProperty = new ExcelHeadProperty(clazz, head); }
}
public void initTableHead() {
if (needHead && null != excelHeadProperty && !CollectionUtils.isEmpty(excelHeadProperty.getHead())) {
int startRow = currentSheet.getLastRowNum();
if (startRow > 0) {
startRow += 4;
} else {
startRow = currentSheetParam.getStartRow();
}
addMergedRegionToCurrentSheet(startRow);
int i = startRow;
for (; i < this.excelHeadProperty.getRowNum() + startRow; i++) {
Row row = WorkBookUtil.createRow(currentSheet, i);
if (null != afterWriteHandler) {
this.afterWriteHandler.row(i, row);
}
addOneRowOfHeadDataToExcel(row, this.excelHeadProperty.getHeadByRowNum(i - startRow));
}
}
}
private void addMergedRegionToCurrentSheet(int startRow) {
for (com.alibaba.excel.metadata.CellRange cellRangeModel : excelHeadProperty.getCellRangeModels()) {
currentSheet.addMergedRegion(new CellRangeAddress(cellRangeModel.getFirstRow() + startRow,
cellRangeModel.getLastRow() + startRow,
cellRangeModel.getFirstCol(), cellRangeModel.getLastCol()));
}
}
private void addOneRowOfHeadDataToExcel(Row row, List<String> headByRowNum) {
if (headByRowNum != null && headByRowNum.size() > 0) {
for (int i = 0; i < headByRowNum.size(); i++) {
Cell cell = WorkBookUtil.createCell(row, i, getCurrentHeadCellStyle(), headByRowNum.get(i));
if (null != afterWriteHandler) {
this.afterWriteHandler.cell(i, cell);
}
}
}
}
private void initTableStyle(com.alibaba.excel.metadata.TableStyle tableStyle) {
if (tableStyle != null) {
this.currentHeadCellStyle = StyleUtil.buildCellStyle(this.workbook, tableStyle.getTableHeadFont(),
tableStyle.getTableHeadBackGroundColor());
this.currentContentCellStyle = StyleUtil.buildCellStyle(this.workbook, tableStyle.getTableContentFont(),
tableStyle.getTableContentBackGroundColor());
}
}
private void cleanCurrentTable() {
this.excelHeadProperty = null;
this.currentHeadCellStyle = null;
this.currentContentCellStyle = null;
this.currentTable = null;
}
public void currentTable(Table table) {
if (null == currentTable || currentTable.getTableNo() != table.getTableNo()) {
cleanCurrentTable();
this.currentTable = table;
this.initExcelHeadProperty(table.getHead(), table.getClazz());
this.initTableStyle(table.getTableStyle());
this.initTableHead();
}
}
public ExcelHeadProperty getExcelHeadProperty() {
return this.excelHeadProperty;
}
public boolean needHead() {
return this.needHead;
}
public Sheet getCurrentSheet() {
return currentSheet;
}
public void setCurrentSheet(Sheet currentSheet) {
this.currentSheet = currentSheet;
}
public String getCurrentSheetName() {
return currentSheetName;
}
public void setCurrentSheetName(String currentSheetName) {
this.currentSheetName = currentSheetName;
}
public ExcelTypeEnum getExcelType() {
return excelType;
}
public void setExcelType(ExcelTypeEnum excelType) {
this.excelType = excelType;
}
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.event.WriteHandler;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import com.alibaba.excel.metadata.Table;
public OutputStream getOutputStream() {
return outputStream;
}
public interface WriteContext {
public CellStyle getCurrentHeadCellStyle() {
return this.currentHeadCellStyle == null ? defaultCellStyle : this.currentHeadCellStyle;
}
Sheet getCurrentSheet();
public CellStyle getCurrentContentStyle() {
return this.currentContentCellStyle;
}
boolean needHead();
public Workbook getWorkbook() {
return workbook;
}
ExcelHeadProperty getExcelHeadProperty();
public com.alibaba.excel.metadata.Sheet getCurrentSheetParam() {
return currentSheetParam;
}
void currentSheet(com.alibaba.excel.metadata.Sheet sheet);
void currentTable(Table table);
public void setCurrentSheetParam(com.alibaba.excel.metadata.Sheet currentSheetParam) {
this.currentSheetParam = currentSheetParam;
}
OutputStream getOutputStream();
public Table getCurrentTable() {
return currentTable;
}
Workbook getWorkbook();
WriteHandler getWriteHandler();
public void setCurrentTable(Table currentTable) {
this.currentTable = currentTable;
}
CellStyle getCurrentContentStyle();
ConverterRegistryCenter getConverterRegistryCenter();
}

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

@ -0,0 +1,311 @@
package com.alibaba.excel.context;
import static com.alibaba.excel.util.StyleUtil.buildSheetStyle;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.event.WriteHandler;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StyleUtil;
import com.alibaba.excel.util.WorkBookUtil;
/**
* A context is the main anchorage point of a excel writer.
*
* @author jipengfei
*/
public class WriteContextImpl implements WriteContext {
/***
* The sheet currently written
*/
private Sheet currentSheet;
/**
* current param
*/
private com.alibaba.excel.metadata.Sheet currentSheetParam;
/**
* The sheet currently written's name
*/
private String currentSheetName;
/**
*
*/
private Table currentTable;
/**
* Excel type
*/
private ExcelTypeEnum excelType;
/**
* POI Workbook
*/
private Workbook workbook;
/**
* Final output stream
*/
private OutputStream outputStream;
/**
* Written form collection
*/
private Map<Integer, Table> tableMap = new ConcurrentHashMap<Integer, Table>();
/**
* Cell default style
*/
private CellStyle defaultCellStyle;
/**
* Current table head style
*/
private CellStyle currentHeadCellStyle;
/**
* Current table content style
*/
private CellStyle currentContentCellStyle;
/**
* the header attribute of excel
*/
private ExcelHeadProperty excelHeadProperty;
private boolean needHead = true;
private WriteHandler writeHandler;
private ConverterRegistryCenter registryCenter;
public WriteHandler getWriteHandler() {
return writeHandler;
}
public WriteContextImpl(InputStream templateInputStream, OutputStream out, ExcelTypeEnum excelType,
boolean needHead, WriteHandler writeHandler, ConverterRegistryCenter registryCenter) throws IOException {
this.needHead = needHead;
this.outputStream = out;
this.writeHandler = writeHandler;
this.workbook = WorkBookUtil.createWorkBook(templateInputStream, excelType);
this.defaultCellStyle = StyleUtil.buildDefaultCellStyle(this.workbook);
this.registryCenter = registryCenter;
}
/**
* @param sheet
*/
@Override
public void currentSheet(com.alibaba.excel.metadata.Sheet sheet) {
if (null == currentSheetParam || currentSheetParam.getSheetNo() != sheet.getSheetNo()) {
cleanCurrentSheet();
currentSheetParam = sheet;
try {
this.currentSheet = workbook.getSheetAt(sheet.getSheetNo() - 1);
} catch (Exception e) {
this.currentSheet = WorkBookUtil.createSheet(workbook, sheet);
if (null != writeHandler) {
this.writeHandler.sheet(sheet.getSheetNo(), currentSheet);
}
}
buildSheetStyle(currentSheet, sheet.getColumnWidthMap());
/** **/
this.initCurrentSheet(sheet);
}
}
private void initCurrentSheet(com.alibaba.excel.metadata.Sheet sheet) {
/** **/
initExcelHeadProperty(sheet.getHead(), sheet.getClazz());
initTableStyle(sheet.getTableStyle());
initTableHead();
}
private void cleanCurrentSheet() {
this.currentSheet = null;
this.currentSheetParam = null;
this.excelHeadProperty = null;
this.currentHeadCellStyle = null;
this.currentContentCellStyle = null;
this.currentTable = null;
}
/**
* init excel header
*
* @param head
* @param clazz
*/
private void initExcelHeadProperty(List<List<String>> head, Class<? extends BaseRowModel> clazz) {
if (head != null || clazz != null) { this.excelHeadProperty = new ExcelHeadProperty(clazz, head); }
}
public void initTableHead() {
if (needHead && null != excelHeadProperty && !CollectionUtils.isEmpty(excelHeadProperty.getHead())) {
int startRow = currentSheet.getLastRowNum();
if (startRow > 0) {
startRow += 4;
} else {
startRow = currentSheetParam.getStartRow();
}
addMergedRegionToCurrentSheet(startRow);
int i = startRow;
for (; i < this.excelHeadProperty.getRowNum() + startRow; i++) {
Row row = WorkBookUtil.createRow(currentSheet, i);
if (null != writeHandler) {
this.writeHandler.row(i, row);
}
addOneRowOfHeadDataToExcel(row, this.excelHeadProperty.getHeadByRowNum(i - startRow));
}
}
}
private void addMergedRegionToCurrentSheet(int startRow) {
for (com.alibaba.excel.metadata.CellRange cellRangeModel : excelHeadProperty.getCellRangeModels()) {
currentSheet.addMergedRegion(new CellRangeAddress(cellRangeModel.getFirstRow() + startRow,
cellRangeModel.getLastRow() + startRow,
cellRangeModel.getFirstCol(), cellRangeModel.getLastCol()));
}
}
private void addOneRowOfHeadDataToExcel(Row row, List<String> headByRowNum) {
if (headByRowNum != null && headByRowNum.size() > 0) {
for (int i = 0; i < headByRowNum.size(); i++) {
Cell cell = WorkBookUtil.createCell(row, i, getCurrentHeadCellStyle(), headByRowNum.get(i));
if (null != writeHandler) {
this.writeHandler.cell(i, cell);
}
}
}
}
private void initTableStyle(com.alibaba.excel.metadata.TableStyle tableStyle) {
if (tableStyle != null) {
this.currentHeadCellStyle = StyleUtil.buildCellStyle(this.workbook, tableStyle.getTableHeadFont(),
tableStyle.getTableHeadBackGroundColor());
this.currentContentCellStyle = StyleUtil.buildCellStyle(this.workbook, tableStyle.getTableContentFont(),
tableStyle.getTableContentBackGroundColor());
}
}
private void cleanCurrentTable() {
this.excelHeadProperty = null;
this.currentHeadCellStyle = null;
this.currentContentCellStyle = null;
this.currentTable = null;
}
@Override
public void currentTable(Table table) {
if (null == currentTable || currentTable.getTableNo() != table.getTableNo()) {
cleanCurrentTable();
this.currentTable = table;
this.initExcelHeadProperty(table.getHead(), table.getClazz());
this.initTableStyle(table.getTableStyle());
this.initTableHead();
}
}
public ExcelHeadProperty getExcelHeadProperty() {
return this.excelHeadProperty;
}
public boolean needHead() {
return this.needHead;
}
@Override
public Sheet getCurrentSheet() {
return currentSheet;
}
public void setCurrentSheet(Sheet currentSheet) {
this.currentSheet = currentSheet;
}
public String getCurrentSheetName() {
return currentSheetName;
}
public void setCurrentSheetName(String currentSheetName) {
this.currentSheetName = currentSheetName;
}
public ExcelTypeEnum getExcelType() {
return excelType;
}
public void setExcelType(ExcelTypeEnum excelType) {
this.excelType = excelType;
}
@Override
public OutputStream getOutputStream() {
return outputStream;
}
public CellStyle getCurrentHeadCellStyle() {
return this.currentHeadCellStyle == null ? defaultCellStyle : this.currentHeadCellStyle;
}
public CellStyle getCurrentContentStyle() {
return this.currentContentCellStyle;
}
@Override
public Workbook getWorkbook() {
return workbook;
}
public com.alibaba.excel.metadata.Sheet getCurrentSheetParam() {
return currentSheetParam;
}
public void setCurrentSheetParam(com.alibaba.excel.metadata.Sheet currentSheetParam) {
this.currentSheetParam = currentSheetParam;
}
public Table getCurrentTable() {
return currentTable;
}
public void setCurrentTable(Table currentTable) {
this.currentTable = currentTable;
}
@Override
public ConverterRegistryCenter getConverterRegistryCenter() {
return registryCenter;
}
}

33
src/main/java/com/alibaba/excel/converters/BigDecimalConverter.java

@ -0,0 +1,33 @@
package com.alibaba.excel.converters;
import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
public class BigDecimalConverter implements Converter {
@Override
public String getName() {
return "big-decimal-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
return BigDecimal.class.equals(columnProperty.getField().getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
return new BigDecimal(value);
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
cell.setCellValue(Double.parseDouble(value.toString()));
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof BigDecimal;
}
}

42
src/main/java/com/alibaba/excel/converters/BooleanConverter.java

@ -0,0 +1,42 @@
package com.alibaba.excel.converters;
import java.lang.reflect.Field;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
public class BooleanConverter implements Converter {
@Override
public String getName() {
return "boolean-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
Field field = columnProperty.getField();
return Boolean.class.equals(field.getType()) || boolean.class.equals(field.getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
String valueLower = value.toLowerCase();
if (valueLower.equals("true") || valueLower.equals("false")) {
return Boolean.parseBoolean(value.toLowerCase());
}
Integer integer = Integer.parseInt(value);
if (integer == 0) {
return false;
} else {
return true;
}
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
cell.setCellValue(String.valueOf(value));
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof Boolean || boolean.class.equals(cellValue.getClass());
}
}

13
src/main/java/com/alibaba/excel/converters/Converter.java

@ -0,0 +1,13 @@
package com.alibaba.excel.converters;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
public interface Converter {
String getName();
boolean support(ExcelColumnProperty columnProperty);
boolean support(Object cellValue);
Object convert(String value, ExcelColumnProperty columnProperty);
Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty);
}

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

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

55
src/main/java/com/alibaba/excel/converters/DateConverter.java

@ -0,0 +1,55 @@
package com.alibaba.excel.converters;
import java.util.Date;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.util.TypeUtil;
public class DateConverter implements Converter {
private final AnalysisContext context;
public DateConverter(AnalysisContext context) {
this.context = context;
}
@Override
public String getName() {
return "date-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
return Date.class.equals(columnProperty.getField().getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
if (value.contains("-") || value.contains("/") || value.contains(":")) {
return TypeUtil.getSimpleDateFormatDate(value, columnProperty.getFormat());
} else {
Double d = Double.parseDouble(value);
return HSSFDateUtil.getJavaDate(d, context != null ? context.use1904WindowDate() : false);
}
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
Date d = (Date)value;
if (columnProperty != null && StringUtils.isEmpty(columnProperty.getFormat()) == false) {
cell.setCellValue(TypeUtil.formatDate(d, columnProperty.getFormat()));
} else {
cell.setCellValue(d);
}
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof Date;
}
}

33
src/main/java/com/alibaba/excel/converters/DoubleConverter.java

@ -0,0 +1,33 @@
package com.alibaba.excel.converters;
import java.lang.reflect.Field;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.util.TypeUtil;
public class DoubleConverter implements Converter {
@Override
public String getName() {
return "double-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
Field field = columnProperty.getField();
return Double.class.equals(field.getType()) || double.class.equals(field.getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
return TypeUtil.formatFloat(value);
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
cell.setCellValue(Double.parseDouble(value.toString()));
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof Double || double.class.equals(cellValue.getClass());
}
}

31
src/main/java/com/alibaba/excel/converters/FloatConverter.java

@ -0,0 +1,31 @@
package com.alibaba.excel.converters;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.util.TypeUtil;
public class FloatConverter implements Converter {
@Override
public String getName() {
return "float-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
return Float.class.equals(columnProperty.getField().getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
return TypeUtil.formatFloat(value);
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
cell.setCellValue(Double.parseDouble(value.toString()));
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof Float || float.class.equals(cellValue.getClass());
}
}

33
src/main/java/com/alibaba/excel/converters/IntegerConverter.java

@ -0,0 +1,33 @@
package com.alibaba.excel.converters;
import java.lang.reflect.Field;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
public class IntegerConverter implements Converter {
@Override
public String getName() {
return "integer-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
Field field = columnProperty.getField();
return Integer.class.equals(field.getType()) || int.class.equals(field.getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
return Integer.parseInt(value);
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
cell.setCellValue(Double.parseDouble(value.toString()));
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof Integer || int.class.equals(cellValue.getClass());
}
}

33
src/main/java/com/alibaba/excel/converters/LongConverter.java

@ -0,0 +1,33 @@
package com.alibaba.excel.converters;
import java.lang.reflect.Field;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
public class LongConverter implements Converter {
@Override
public String getName() {
return "long-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
Field field = columnProperty.getField();
return Long.class.equals(field.getType()) || long.class.equals(field.getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
return Long.parseLong(value);
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
cell.setCellValue(Double.parseDouble(value.toString()));
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof Long || long.class.equals(cellValue.getClass());
}
}

31
src/main/java/com/alibaba/excel/converters/StringConverter.java

@ -0,0 +1,31 @@
package com.alibaba.excel.converters;
import org.apache.poi.ss.usermodel.Cell;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.util.TypeUtil;
public class StringConverter implements Converter {
@Override
public String getName() {
return "string-converter";
}
@Override
public boolean support(ExcelColumnProperty columnProperty) {
return String.class.equals(columnProperty.getField().getType());
}
@Override
public Object convert(String value, ExcelColumnProperty columnProperty) {
return TypeUtil.formatFloat(value);
}
@Override
public Cell convert(Cell cell, Object value, ExcelColumnProperty columnProperty) {
cell.setCellValue(String.valueOf(value));
return cell;
}
@Override
public boolean support(Object cellValue) {
return cellValue instanceof String;
}
}

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

@ -12,7 +12,7 @@ public abstract class AnalysisEventListener<T> {
/**
* when analysis one row trigger invoke function
*
* @param object one row data
* @param object one row value
* @param context analysis context
*/
public abstract void invoke(T object, AnalysisContext context);

12
src/main/java/com/alibaba/excel/event/AnalysisEventRegisterCenter.java → src/main/java/com/alibaba/excel/event/AnalysisEventRegistryCenter.java

@ -5,7 +5,7 @@ package com.alibaba.excel.event;
*
* @author jipengfei
*/
public interface AnalysisEventRegisterCenter {
public interface AnalysisEventRegistryCenter {
/**
* Append listener
@ -13,17 +13,23 @@ public interface AnalysisEventRegisterCenter {
* @param name listener name.
* @param listener Callback method after each row is parsed.
*/
void appendLister(String name, AnalysisEventListener listener);
void register(String name, AnalysisEventListener<Object> listener);
/**
* Parse one row to notify all event listeners
*
* @param event parse event
*/
void notifyListeners(OneRowAnalysisFinishEvent event);
void notify(AnalysisFinishEvent event);
/**
* Clean all listeners.
*/
void cleanAllListeners();
/**
* clean listener by name
* @param name the listener name
*/
void cleanListener(String name);
}

5
src/main/java/com/alibaba/excel/event/AnalysisFinishEvent.java

@ -0,0 +1,5 @@
package com.alibaba.excel.event;
public interface AnalysisFinishEvent {
Object getAnalysisResult();
}

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

@ -0,0 +1,29 @@
package com.alibaba.excel.event;
import java.util.ArrayList;
import java.util.List;
/**
* @author jipengfei
*/
public class EachRowAnalysisFinishEvent implements AnalysisFinishEvent {
private Object result;
public EachRowAnalysisFinishEvent(Object content) {
this.result = content;
}
public EachRowAnalysisFinishEvent(String[] content, int length) {
if (content != null) {
List<String> ls = new ArrayList<String>(length);
for (int i = 0; i <= length; i++) {
ls.add(content[i]);
}
result = ls;
}
}
@Override
public Object getAnalysisResult() {
return result;
}
}

44
src/main/java/com/alibaba/excel/modelbuild/ModelBuildEventListener.java → src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java

@ -1,23 +1,34 @@
package com.alibaba.excel.modelbuild;
package com.alibaba.excel.event;
import java.util.Collection;
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.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import com.alibaba.excel.util.TypeUtil;
import net.sf.cglib.beans.BeanMap;
import java.util.List;
import net.sf.cglib.beans.BeanMap;
/**
* @author jipengfei
*/
public class ModelBuildEventListener extends AnalysisEventListener {
public class ModelBuildEventListener extends AnalysisEventListener<Object> {
private final Collection<Converter> converters;
public ModelBuildEventListener(Collection<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<String>)object);
context.setCurrentRowAnalysisResult(resultModel);
} catch (Exception e) {
@ -26,17 +37,36 @@ public class ModelBuildEventListener extends AnalysisEventListener {
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private Object buildUserModel(AnalysisContext context, List<String> stringList) throws Exception {
ExcelHeadProperty excelHeadProperty = context.getExcelHeadProperty();
Object resultModel = excelHeadProperty.getHeadClazz().newInstance();
if (excelHeadProperty == null) {
return resultModel;
}
BeanMap.create(resultModel).putAll(
TypeUtil.getFieldValues(stringList, excelHeadProperty, context.use1904WindowDate()));
Map map = new HashMap();
for (int i = 0; i < stringList.size(); i++) {
ExcelColumnProperty columnProperty = excelHeadProperty.getExcelColumnProperty(i);
if (columnProperty != null) {
Object value = convertValue(stringList.get(i), columnProperty);
if (value != null) {
map.put(columnProperty.getField().getName(), value);
}
}
}
BeanMap.create(resultModel).putAll(map);
return resultModel;
}
private Object convertValue(String value, ExcelColumnProperty columnProperty) {
for (Converter c : converters) {
if (c.support(columnProperty)) {
return c.convert(value, columnProperty);
}
}
return null;
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {

34
src/main/java/com/alibaba/excel/event/OneRowAnalysisFinishEvent.java

@ -1,34 +0,0 @@
package com.alibaba.excel.event;
import java.util.ArrayList;
import java.util.List;
/**
* @author jipengfei
*/
public class OneRowAnalysisFinishEvent {
public OneRowAnalysisFinishEvent(Object content) {
this.data = content;
}
public OneRowAnalysisFinishEvent(String[] content, int length) {
if (content != null) {
List<String> ls = new ArrayList<String>(length);
for (int i = 0; i <= length; i++) {
ls.add(content[i]);
}
data = ls;
}
}
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}

14
src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java

@ -123,11 +123,11 @@ public class ExcelHeadProperty {
return excelColumnPropertyMap1.get(columnNum);
}
public Class getHeadClazz() {
public Class<? extends BaseRowModel> getHeadClazz() {
return headClazz;
}
public void setHeadClazz(Class headClazz) {
public void setHeadClazz(Class<? extends BaseRowModel> headClazz) {
this.headClazz = headClazz;
}
@ -224,5 +224,13 @@ public class ExcelHeadProperty {
}
return headRowNum;
}
public static ExcelHeadProperty buildExcelHeadProperty(ExcelHeadProperty excelHeadProperty, Class<? extends BaseRowModel> clazz, List<String> headOneRow) {
if (excelHeadProperty == null && (clazz != null || headOneRow != null)) {
excelHeadProperty = new ExcelHeadProperty(clazz, new ArrayList<List<String>>());
}
if (excelHeadProperty.getHead() == null && headOneRow != null) {
excelHeadProperty.appendOneRow(headOneRow);
}
return excelHeadProperty;
}
}

10
src/main/java/com/alibaba/excel/parameter/GenerateParam.java

@ -17,6 +17,8 @@ public class GenerateParam {
private ExcelTypeEnum type;
private boolean needHead = true;
public GenerateParam(String sheetName, Class clazz, OutputStream outputStream) {
this.outputStream = outputStream;
this.sheetName = sheetName;
@ -55,4 +57,12 @@ public class GenerateParam {
public void setType(ExcelTypeEnum type) {
this.type = type;
}
public boolean isNeedHead() {
return needHead;
}
public void setNeedHead(boolean needHead) {
this.needHead = needHead;
}
}

126
src/main/java/com/alibaba/excel/util/TypeUtil.java

@ -1,18 +1,22 @@
package com.alibaba.excel.util;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.metadata.ExcelHeadProperty;
import net.sf.cglib.beans.BeanMap;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.metadata.ExcelHeadProperty;
/**
* @author jipengfei
*/
@ -26,70 +30,6 @@ public class TypeUtil {
DATE_FORMAT_LIST.add("yyyyMMdd HH:mm:ss");
}
private static int getCountOfChar(String value, char c) {
int n = 0;
if (value == null) {
return 0;
}
char[] chars = value.toCharArray();
for (char cc : chars) {
if (cc == c) {
n++;
}
}
return n;
}
public static Object convert(String value, Field field, String format, boolean us) {
if (!StringUtils.isEmpty(value)) {
if (Float.class.equals(field.getType())) {
return Float.parseFloat(value);
}
if (Integer.class.equals(field.getType()) || int.class.equals(field.getType())) {
return Integer.parseInt(value);
}
if (Double.class.equals(field.getType()) || double.class.equals(field.getType())) {
if (null != format && !"".equals(format)) {
int n = getCountOfChar(value, '0');
return Double.parseDouble(TypeUtil.formatFloat0(value, n));
} else {
return Double.parseDouble(TypeUtil.formatFloat(value));
}
}
if (Boolean.class.equals(field.getType()) || boolean.class.equals(field.getType())) {
String valueLower = value.toLowerCase();
if (valueLower.equals("true") || valueLower.equals("false")) {
return Boolean.parseBoolean(value.toLowerCase());
}
Integer integer = Integer.parseInt(value);
if (integer == 0) {
return false;
} else {
return true;
}
}
if (Long.class.equals(field.getType()) || long.class.equals(field.getType())) {
return Long.parseLong(value);
}
if (Date.class.equals(field.getType())) {
if (value.contains("-") || value.contains("/") || value.contains(":")) {
return getSimpleDateFormatDate(value, format);
} else {
Double d = Double.parseDouble(value);
return HSSFDateUtil.getJavaDate(d, us);
}
}
if (BigDecimal.class.equals(field.getType())) {
return new BigDecimal(value);
}
if(String.class.equals(field.getType())){
return formatFloat(value);
}
}
return null;
}
public static Boolean isNum(Field field) {
if (field == null) {
return false;
@ -112,12 +52,8 @@ public class TypeUtil {
}
public static Boolean isNum(Object cellValue) {
if (cellValue instanceof Integer
|| cellValue instanceof Double
|| cellValue instanceof Short
|| cellValue instanceof Long
|| cellValue instanceof Float
|| cellValue instanceof BigDecimal) {
if (cellValue instanceof Integer || cellValue instanceof Double || cellValue instanceof Short
|| cellValue instanceof Long || cellValue instanceof Float || cellValue instanceof BigDecimal) {
return true;
}
return false;
@ -164,7 +100,7 @@ public class TypeUtil {
if (isNumeric(value)) {
try {
BigDecimal decimal = new BigDecimal(value);
BigDecimal setScale = decimal.setScale(10, BigDecimal.ROUND_HALF_DOWN).stripTrailingZeros();
BigDecimal setScale = decimal.setScale(10, RoundingMode.HALF_DOWN).stripTrailingZeros();
return setScale.toPlainString();
} catch (Exception e) {
}
@ -178,7 +114,7 @@ public class TypeUtil {
if (isNumeric(value)) {
try {
BigDecimal decimal = new BigDecimal(value);
BigDecimal setScale = decimal.setScale(n, BigDecimal.ROUND_HALF_DOWN);
BigDecimal setScale = decimal.setScale(n, RoundingMode.HALF_DOWN);
return setScale.toPlainString();
} catch (Exception e) {
}
@ -199,39 +135,11 @@ public class TypeUtil {
public static String formatDate(Date cellValue, String format) {
SimpleDateFormat simpleDateFormat;
if(!StringUtils.isEmpty(format)) {
simpleDateFormat = new SimpleDateFormat(format);
}else {
if (!StringUtils.isEmpty(format)) {
simpleDateFormat = new SimpleDateFormat(format);
} else {
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
return simpleDateFormat.format(cellValue);
}
public static String getFieldStringValue(BeanMap beanMap, String fieldName, String format) {
String cellValue = null;
Object value = beanMap.get(fieldName);
if (value != null) {
if (value instanceof Date) {
cellValue = TypeUtil.formatDate((Date)value, format);
} else {
cellValue = value.toString();
}
}
return cellValue;
}
public static Map getFieldValues(List<String> stringList, ExcelHeadProperty excelHeadProperty, Boolean use1904WindowDate) {
Map map = new HashMap();
for (int i = 0; i < stringList.size(); i++) {
ExcelColumnProperty columnProperty = excelHeadProperty.getExcelColumnProperty(i);
if (columnProperty != null) {
Object value = TypeUtil.convert(stringList.get(i), columnProperty.getField(),
columnProperty.getFormat(), use1904WindowDate);
if (value != null) {
map.put(columnProperty.getField().getName(),value);
}
}
}
return map;
}
}

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

@ -54,22 +54,16 @@ public class WorkBookUtil {
public static Row createRow(Sheet sheet, int rowNum) {
return sheet.createRow(rowNum);
}
public static Cell createCell(Row row, int colNum, CellStyle cellStyle, String cellValue) {
return createCell(row, colNum, cellStyle, cellValue, false);
}
public static Cell createCell(Row row, int colNum, CellStyle cellStyle, Object cellValue, Boolean isNum) {
public static Cell createCell(Row row, int colNum, CellStyle cellStyle) {
Cell cell = row.createCell(colNum);
cell.setCellStyle(cellStyle);
if (null != cellValue) {
if (isNum) {
cell.setCellValue(Double.parseDouble(cellValue.toString()));
} else {
cell.setCellValue(cellValue.toString());
}
}
return cell;
}
public static Cell createCell(Row row, int colNum, CellStyle cellStyle, String cellValue) {
Cell cell = createCell(row, colNum, cellStyle);
cell.setCellValue(cellValue);
return cell;
}
}

13
src/main/java/com/alibaba/excel/write/ExcelBuilder.java

@ -11,7 +11,7 @@ import java.util.List;
public interface ExcelBuilder {
/**
* workBook increase data
* workBook increase value
*
* @param data java basic type or java model extend BaseModel
* @param startRow Start row number
@ -19,7 +19,7 @@ public interface ExcelBuilder {
void addContent(List data, int startRow);
/**
* WorkBook increase data
* WorkBook increase value
*
* @param data java basic type or java model extend BaseModel
* @param sheetParam Write the sheet
@ -27,7 +27,7 @@ public interface ExcelBuilder {
void addContent(List data, Sheet sheetParam);
/**
* WorkBook increase data
* WorkBook increase value
*
* @param data java basic type or java model extend BaseModel
* @param sheetParam Write the sheet
@ -38,12 +38,9 @@ public interface ExcelBuilder {
/**
* Creates new cell range. Indexes are zero-based.
*
* @param firstRow Index of first row
* @param lastRow Index of last row (inclusive), must be equal to or larger than {@code firstRow}
* @param firstCol Index of first column
* @param lastCol Index of last column (inclusive), must be equal to or larger than {@code firstCol}
* @param strategies the merge strategy
*/
void merge(int firstRow, int lastRow, int firstCol, int lastCol);
void merge(List<MergeStrategy> strategies);
/**
* Close io

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

@ -1,6 +1,20 @@
package com.alibaba.excel.write;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.context.WriteContextImpl;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ConverterRegistryCenter;
import com.alibaba.excel.event.WriteHandler;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.BaseRowModel;
@ -12,32 +26,28 @@ import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.POITempFile;
import com.alibaba.excel.util.TypeUtil;
import com.alibaba.excel.util.WorkBookUtil;
import net.sf.cglib.beans.BeanMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import net.sf.cglib.beans.BeanMap;
/**
* @author jipengfei
*/
public class ExcelBuilderImpl implements ExcelBuilder {
public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter {
private WriteContext context;
private final List<Converter> converters = new ArrayList<Converter>();
public ExcelBuilderImpl(InputStream templateInputStream,
OutputStream out,
ExcelTypeEnum excelType,
boolean needHead, WriteHandler writeHandler) {
boolean needHead, WriteHandler writeHandler, List<Converter> converters) {
try {
//初始化时候创建临时缓存目录,用于规避POI在并发写bug
POITempFile.createPOIFilesDirectory();
context = new WriteContext(templateInputStream, out, excelType, needHead, writeHandler);
if (converters != null) {
converters.addAll(converters);
}
context = new WriteContextImpl(templateInputStream, out, excelType, needHead, writeHandler, this);
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -80,9 +90,13 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
@Override
public void merge(int firstRow, int lastRow, int firstCol, int lastCol) {
CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
context.getCurrentSheet().addMergedRegion(cra);
public void merge(List<MergeStrategy> strategies) {
if (strategies != null) {
for (MergeStrategy ms : strategies) {
CellRangeAddress cra = new CellRangeAddress(ms.getFirstRow(), ms.getLastRow(), ms.getFirstCol(), ms.getLastCol());
context.getCurrentSheet().addMergedRegion(cra);
}
}
}
@Override
@ -101,10 +115,10 @@ public class ExcelBuilderImpl implements ExcelBuilder {
}
for (int i = 0; i < oneRowData.size(); i++) {
Object cellValue = oneRowData.get(i);
Cell cell = WorkBookUtil.createCell(row, i, context.getCurrentContentStyle(), cellValue,
TypeUtil.isNum(cellValue));
if (null != context.getAfterWriteHandler()) {
context.getAfterWriteHandler().cell(i, cell);
Cell cell = WorkBookUtil.createCell(row, i, context.getCurrentContentStyle());
cell = convertValue(cell, cellValue, null);
if (null != context.getWriteHandler()) {
context.getWriteHandler().cell(i, cell);
}
}
}
@ -114,24 +128,33 @@ public class ExcelBuilderImpl implements ExcelBuilder {
BeanMap beanMap = BeanMap.create(oneRowData);
for (ExcelColumnProperty excelHeadProperty : context.getExcelHeadProperty().getColumnPropertyList()) {
BaseRowModel baseRowModel = (BaseRowModel)oneRowData;
String cellValue = TypeUtil.getFieldStringValue(beanMap, excelHeadProperty.getField().getName(),
excelHeadProperty.getFormat());
CellStyle cellStyle = baseRowModel.getStyle(i) != null ? baseRowModel.getStyle(i)
: context.getCurrentContentStyle();
Cell cell = WorkBookUtil.createCell(row, i, cellStyle, cellValue,
TypeUtil.isNum(excelHeadProperty.getField()));
if (null != context.getAfterWriteHandler()) {
context.getAfterWriteHandler().cell(i, cell);
: context.getCurrentContentStyle();
Object value = beanMap.get(excelHeadProperty.getField().getName());
Cell cell = WorkBookUtil.createCell(row, i, cellStyle);
cell = convertValue(cell, value, excelHeadProperty);
if (null != context.getWriteHandler()) {
context.getWriteHandler().cell(i, cell);
}
i++;
}
}
private Cell convertValue(Cell cell, Object value, ExcelColumnProperty excelHeadProperty) {
if (!CollectionUtils.isEmpty(this.converters)) {
for (Converter c : this.converters) {
if (value != null && c.support(value)) {
return c.convert(cell, value, excelHeadProperty);
}
}
}
return cell;
}
private void addOneRowOfDataToExcel(Object oneRowData, int n) {
Row row = WorkBookUtil.createRow(context.getCurrentSheet(), n);
if (null != context.getAfterWriteHandler()) {
context.getAfterWriteHandler().row(n, row);
if (null != context.getWriteHandler()) {
context.getWriteHandler().row(n, row);
}
if (oneRowData instanceof List) {
addBasicTypeToExcel((List)oneRowData, row);
@ -139,4 +162,14 @@ public class ExcelBuilderImpl implements ExcelBuilder {
addJavaObjectToExcel(oneRowData, row);
}
}
@Override
public void register(Converter converter) {
this.converters.add(converter);
}
@Override
public List<Converter> getConverters() {
return this.converters;
}
}

8
src/main/java/com/alibaba/excel/write/MergeStrategy.java

@ -0,0 +1,8 @@
package com.alibaba.excel.write;
public interface MergeStrategy {
int getFirstRow();
int getLastRow();
int getFirstCol();
int getLastCol();
}

8
src/test/java/com/alibaba/easyexcel/test/ReadTest.java

@ -161,13 +161,13 @@ public class ReadTest {
public void saxReadSheetsV2003() throws IOException {
InputStream inputStream = FileUtil.getResourcesFileInputStream("2003.xls");
ExcelListener excelListener = new ExcelListener();
ExcelReader excelReader = EasyExcelFactory.getReader(inputStream,excelListener);
ExcelReader excelReader = EasyExcelFactory.getReader(inputStream, excelListener);
List<Sheet> sheets = excelReader.getSheets();
System.out.println();
for (Sheet sheet:sheets) {
if(sheet.getSheetNo() == 1) {
for (Sheet sheet : sheets) {
if (sheet.getSheetNo() == 1) {
excelReader.read(sheet);
}else {
} else {
sheet.setHeadLineMun(2);
sheet.setClazz(ReadModel.class);
excelReader.read(sheet);

148
src/test/java/com/alibaba/easyexcel/test/WriteTest.java

@ -1,5 +1,22 @@
package com.alibaba.easyexcel.test;
import static com.alibaba.easyexcel.test.util.DataUtil.createTableStyle;
import static com.alibaba.easyexcel.test.util.DataUtil.createTestListJavaMode;
import static com.alibaba.easyexcel.test.util.DataUtil.createTestListObject;
import static com.alibaba.easyexcel.test.util.DataUtil.createTestListStringHead;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import com.alibaba.easyexcel.test.listen.AfterWriteHandlerImpl;
import com.alibaba.easyexcel.test.model.WriteModel;
import com.alibaba.easyexcel.test.util.FileUtil;
@ -8,49 +25,69 @@ import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import org.junit.Test;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import static com.alibaba.easyexcel.test.util.DataUtil.*;
import com.alibaba.excel.write.MergeStrategy;
public class WriteTest {
@Test
public void writeV2007() throws IOException {
OutputStream out = new FileOutputStream("/Users/jipengfei/2007.xlsx");
OutputStream out = new FileOutputStream(new File(FileUtil.getPath(), "write_2007.xlsx"));
ExcelWriter writer = EasyExcelFactory.getWriter(out);
//写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
// 写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
Sheet sheet1 = new Sheet(1, 3);
sheet1.setSheetName("第一个sheet");
//设置列宽 设置每列的宽度
// 设置列宽 设置每列的宽度
Map columnWidth = new HashMap();
columnWidth.put(0,10000);columnWidth.put(1,40000);columnWidth.put(2,10000);columnWidth.put(3,10000);
columnWidth.put(0, 10000);
columnWidth.put(1, 40000);
columnWidth.put(2, 10000);
columnWidth.put(3, 10000);
sheet1.setColumnWidthMap(columnWidth);
sheet1.setHead(createTestListStringHead());
//or 设置自适应宽度
//sheet1.setAutoWidth(Boolean.TRUE);
// or 设置自适应宽度
// sheet1.setAutoWidth(Boolean.TRUE);
writer.write1(createTestListObject(), sheet1);
//写第二个sheet sheet2 模型上打有表头的注解,合并单元格
// 写第二个sheet sheet2 模型上打有表头的注解,合并单元格
Sheet sheet2 = new Sheet(2, 3, WriteModel.class, "第二个sheet", null);
sheet2.setTableStyle(createTableStyle());
//writer.write1(null, sheet2);
// writer.write1(null, sheet2);
writer.write(createTestListJavaMode(), sheet2);
//需要合并单元格
writer.merge(5,20,1,1);
//写第三个sheet包含多个table情况
List<MergeStrategy> strategies = new ArrayList<MergeStrategy>();
strategies.add(new MergeStrategy() {
@Override
public int getFirstRow() {
return 5;
}
@Override
public int getLastRow() {
return 20;
}
@Override
public int getFirstCol() {
return 1;
}
@Override
public int getLastCol() {
return 1;
}
});
// 需要合并单元格
writer.merge(strategies);
// 写第三个sheet包含多个table情况
Sheet sheet3 = new Sheet(3, 0);
sheet3.setSheetName("第三个sheet");
Table table1 = new Table(1);
table1.setHead(createTestListStringHead());
writer.write1(createTestListObject(), sheet3, table1);
//写sheet2 模型上打有表头的注解
// 写sheet2 模型上打有表头的注解
Table table2 = new Table(2);
table2.setTableStyle(createTableStyle());
table2.setClazz(WriteModel.class);
@ -65,29 +102,32 @@ public class WriteTest {
@Test
public void writeV2007WithTemplate() throws IOException {
InputStream inputStream = FileUtil.getResourcesFileInputStream("temp.xlsx");
OutputStream out = new FileOutputStream("/Users/jipengfei/2007.xlsx");
ExcelWriter writer = EasyExcelFactory.getWriterWithTemp(inputStream,out,ExcelTypeEnum.XLSX,true);
//写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
OutputStream out = new FileOutputStream(new File(FileUtil.getPath(), "write_2007_1.xlsx"));
ExcelWriter writer = EasyExcelFactory.getWriterWithTemp(inputStream, out, ExcelTypeEnum.XLSX, true);
// 写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
Sheet sheet1 = new Sheet(1, 3);
sheet1.setSheetName("第一个sheet");
sheet1.setStartRow(20);
//设置列宽 设置每列的宽度
// 设置列宽 设置每列的宽度
Map columnWidth = new HashMap();
columnWidth.put(0,10000);columnWidth.put(1,40000);columnWidth.put(2,10000);columnWidth.put(3,10000);
columnWidth.put(0, 10000);
columnWidth.put(1, 40000);
columnWidth.put(2, 10000);
columnWidth.put(3, 10000);
sheet1.setColumnWidthMap(columnWidth);
sheet1.setHead(createTestListStringHead());
//or 设置自适应宽度
//sheet1.setAutoWidth(Boolean.TRUE);
// or 设置自适应宽度
// sheet1.setAutoWidth(Boolean.TRUE);
writer.write1(createTestListObject(), sheet1);
//写第二个sheet sheet2 模型上打有表头的注解,合并单元格
// 写第二个sheet sheet2 模型上打有表头的注解,合并单元格
Sheet sheet2 = new Sheet(2, 3, WriteModel.class, "第二个sheet", null);
sheet2.setTableStyle(createTableStyle());
sheet2.setStartRow(20);
writer.write(createTestListJavaMode(), sheet2);
//写第三个sheet包含多个table情况
// 写第三个sheet包含多个table情况
Sheet sheet3 = new Sheet(3, 0);
sheet3.setSheetName("第三个sheet");
sheet3.setStartRow(30);
@ -95,7 +135,7 @@ public class WriteTest {
table1.setHead(createTestListStringHead());
writer.write1(createTestListObject(), sheet3, table1);
//写sheet2 模型上打有表头的注解
// 写sheet2 模型上打有表头的注解
Table table2 = new Table(2);
table2.setTableStyle(createTableStyle());
table2.setClazz(WriteModel.class);
@ -109,30 +149,33 @@ public class WriteTest {
@Test
public void writeV2007WithTemplateAndHandler() throws IOException {
InputStream inputStream = FileUtil.getResourcesFileInputStream("temp.xlsx");
OutputStream out = new FileOutputStream("/Users/jipengfei/2007.xlsx");
ExcelWriter writer = EasyExcelFactory.getWriterWithTempAndHandler(inputStream,out,ExcelTypeEnum.XLSX,true,
new AfterWriteHandlerImpl());
//写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
OutputStream out = new FileOutputStream(new File(FileUtil.getPath(), "write_2007_2.xlsx"));
ExcelWriter writer = EasyExcelFactory.getWriterWithTempAndHandler(inputStream, out, ExcelTypeEnum.XLSX, true,
new AfterWriteHandlerImpl());
// 写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
Sheet sheet1 = new Sheet(1, 3);
sheet1.setSheetName("第一个sheet");
sheet1.setStartRow(20);
//设置列宽 设置每列的宽度
// 设置列宽 设置每列的宽度
Map columnWidth = new HashMap();
columnWidth.put(0,10000);columnWidth.put(1,40000);columnWidth.put(2,10000);columnWidth.put(3,10000);
columnWidth.put(0, 10000);
columnWidth.put(1, 40000);
columnWidth.put(2, 10000);
columnWidth.put(3, 10000);
sheet1.setColumnWidthMap(columnWidth);
sheet1.setHead(createTestListStringHead());
//or 设置自适应宽度
//sheet1.setAutoWidth(Boolean.TRUE);
// or 设置自适应宽度
// sheet1.setAutoWidth(Boolean.TRUE);
writer.write1(createTestListObject(), sheet1);
//写第二个sheet sheet2 模型上打有表头的注解,合并单元格
// 写第二个sheet sheet2 模型上打有表头的注解,合并单元格
Sheet sheet2 = new Sheet(2, 3, WriteModel.class, "第二个sheet", null);
sheet2.setTableStyle(createTableStyle());
sheet2.setStartRow(20);
writer.write(createTestListJavaMode(), sheet2);
//写第三个sheet包含多个table情况
// 写第三个sheet包含多个table情况
Sheet sheet3 = new Sheet(3, 0);
sheet3.setSheetName("第三个sheet");
sheet3.setStartRow(30);
@ -140,7 +183,7 @@ public class WriteTest {
table1.setHead(createTestListStringHead());
writer.write1(createTestListObject(), sheet3, table1);
//写sheet2 模型上打有表头的注解
// 写sheet2 模型上打有表头的注解
Table table2 = new Table(2);
table2.setTableStyle(createTableStyle());
table2.setClazz(WriteModel.class);
@ -155,34 +198,37 @@ public class WriteTest {
@Test
public void writeV2003() throws IOException {
OutputStream out = new FileOutputStream("/Users/jipengfei/2003.xls");
ExcelWriter writer = EasyExcelFactory.getWriter(out, ExcelTypeEnum.XLS,true);
//写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
OutputStream out = new FileOutputStream(new File(FileUtil.getPath(), "write_2003.xlsx"));
ExcelWriter writer = EasyExcelFactory.getWriter(out, ExcelTypeEnum.XLS, true);
// 写第一个sheet, sheet1 数据全是List<String> 无模型映射关系
Sheet sheet1 = new Sheet(1, 3);
sheet1.setSheetName("第一个sheet");
//设置列宽 设置每列的宽度
// 设置列宽 设置每列的宽度
Map columnWidth = new HashMap();
columnWidth.put(0,10000);columnWidth.put(1,40000);columnWidth.put(2,10000);columnWidth.put(3,10000);
columnWidth.put(0, 10000);
columnWidth.put(1, 40000);
columnWidth.put(2, 10000);
columnWidth.put(3, 10000);
sheet1.setColumnWidthMap(columnWidth);
sheet1.setHead(createTestListStringHead());
//or 设置自适应宽度
//sheet1.setAutoWidth(Boolean.TRUE);
// or 设置自适应宽度
// sheet1.setAutoWidth(Boolean.TRUE);
writer.write1(createTestListObject(), sheet1);
//写第二个sheet sheet2 模型上打有表头的注解,合并单元格
// 写第二个sheet sheet2 模型上打有表头的注解,合并单元格
Sheet sheet2 = new Sheet(2, 3, WriteModel.class, "第二个sheet", null);
sheet2.setTableStyle(createTableStyle());
writer.write(createTestListJavaMode(), sheet2);
//写第三个sheet包含多个table情况
// 写第三个sheet包含多个table情况
Sheet sheet3 = new Sheet(3, 0);
sheet3.setSheetName("第三个sheet");
Table table1 = new Table(1);
table1.setHead(createTestListStringHead());
writer.write1(createTestListObject(), sheet3, table1);
//写sheet2 模型上打有表头的注解
// 写sheet2 模型上打有表头的注解
Table table2 = new Table(2);
table2.setTableStyle(createTableStyle());
table2.setClazz(WriteModel.class);

2
src/test/java/com/alibaba/easyexcel/test/model/WriteModel.java

@ -25,7 +25,7 @@ public class WriteModel extends BaseWriteModel {
@ExcelProperty(value = {"表头6","表头61","表头612"},index = 6)
private BigDecimal p7;
@ExcelProperty(value = {"表头6","表头62","表头621"},index = 7)
@ExcelProperty(value = {"表头6","表头62","表头621"},index = 7, format = "yyyy-MM-dd")
private Date p8;
@ExcelProperty(value = {"表头6","表头62","表头622"},index = 8)

4
src/test/java/com/alibaba/easyexcel/test/util/FileUtil.java

@ -7,4 +7,8 @@ public class FileUtil {
public static InputStream getResourcesFileInputStream(String fileName) {
return Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName);
}
public static String getPath() {
return FileUtil.class.getResource("/").getPath();
}
}

Loading…
Cancel
Save