From c343e4ae39f87109ee10f17bb0850b7bfbfea433 Mon Sep 17 00:00:00 2001 From: zhuangjiaju Date: Thu, 11 Jul 2019 16:55:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AD=96=E7=95=A5=E6=8E=92?= =?UTF-8?q?=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 12 +- .../com/alibaba/excel/EasyExcelFactory.java | 54 +++- .../java/com/alibaba/excel/ExcelWriter.java | 230 +++++++------ .../excel/analysis/BaseSaxAnalyser.java | 31 +- .../analysis/v07/XlsxRowResultHolder.java | 6 +- .../v07/handlers/DefaultCellHandler.java | 105 +++--- .../excel/constant/ExcelXmlConstants.java | 2 + .../alibaba/excel/context/WriteContext.java | 50 +-- .../excel/context/WriteContextImpl.java | 302 ++++++++++++------ .../excel/converters/BigDecimalConverter.java | 33 -- .../excel/converters/BooleanConverter.java | 42 --- .../alibaba/excel/converters/Converter.java | 20 +- .../excel/converters/ConverterKey.java | 48 +++ .../excel/converters/DateConverter.java | 55 ---- .../excel/converters/DoubleConverter.java | 33 -- .../excel/converters/FloatConverter.java | 31 -- .../excel/converters/IntegerConverter.java | 33 -- .../excel/converters/LongConverter.java | 33 -- .../excel/converters/StringConverter.java | 31 -- .../BigDecimalBooleanConverter.java | 42 +++ .../bigdecimal/BigDecimalNumberConverter.java | 36 +++ .../bigdecimal/BigDecimalStringConverter.java | 41 +++ .../converters/date/DateNumberConverter.java | 39 +++ .../converters/date/DateStringConverter.java | 37 +++ .../alibaba/excel/enums/CellDataTypeEnum.java | 54 ++++ .../com/alibaba/excel/enums/HeadKindEnum.java | 2 +- .../event/EachRowAnalysisFinishEvent.java | 6 +- .../excel/event/ModelBuildEventListener.java | 13 +- .../excel/event/NotRepeatExecutor.java | 16 + .../java/com/alibaba/excel/event/Order.java | 15 + .../com/alibaba/excel/event/WriteHandler.java | 42 --- .../exception/ExcelDataConvertException.java | 21 ++ .../alibaba/excel/metadata/BaseRowModel.java | 34 -- .../com/alibaba/excel/metadata/CellData.java | 138 ++++++++ .../com/alibaba/excel/metadata/CellStyle.java | 11 +- .../excel/metadata/ExcelColumnProperty.java | 24 +- .../excel/metadata/ExcelHeadProperty.java | 18 +- .../java/com/alibaba/excel/metadata/Head.java | 46 ++- .../com/alibaba/excel/metadata/Sheet.java | 179 ++++------- .../alibaba/excel/metadata/SheetHolder.java | 104 ------ .../com/alibaba/excel/metadata/Table.java | 105 ++++-- .../holder/ConfigurationSelector.java | 43 +++ .../excel/metadata/holder/SheetHolder.java | 131 ++++++++ .../metadata/{ => holder}/TableHolder.java | 6 +- .../excel/metadata/holder/WorkbookHolder.java | 92 ++++++ .../com/alibaba/excel/util/BooleanUtils.java | 29 ++ .../com/alibaba/excel/util/DateUtils.java | 101 ++++++ .../com/alibaba/excel/util/StyleUtil.java | 66 ++-- .../java/com/alibaba/excel/util/TypeUtil.java | 145 --------- .../com/alibaba/excel/util/WorkBookUtil.java | 16 - .../com/alibaba/excel/write/ExcelBuilder.java | 21 +- .../alibaba/excel/write/ExcelBuilderImpl.java | 81 ++--- .../excel/write/ExcelWriterBuilder.java | 30 -- .../write/builder/ExcelWriterBuilder.java | 120 +++++++ ...riteHandler.java => CellWriteHandler.java} | 6 +- ...WriteHandler.java => RowWriteHandler.java} | 6 +- ...iteHandler.java => SheetWriteHandler.java} | 4 +- .../write/handler/WorkbookWriteHandler.java | 25 ++ ...celWriteHandler.java => WriteHandler.java} | 2 +- .../write/merge/AbstractMergeStrategy.java | 8 +- .../style/AbstractCellStyleStrategy.java | 21 +- ...a => AbstractColumnCellStyleStrategy.java} | 11 +- ...trategy.java => RowCellStyleStrategy.java} | 36 ++- .../AbstractColumnWidthStyleStrategy.java | 14 +- .../AbstractHeadColumnWidthStyleStrategy.java | 2 +- .../row/AbstractRowHighStyleStrategy.java | 14 +- src/test/resources/logback.xml | 16 + 67 files changed, 1896 insertions(+), 1324 deletions(-) delete mode 100644 src/main/java/com/alibaba/excel/converters/BigDecimalConverter.java delete mode 100644 src/main/java/com/alibaba/excel/converters/BooleanConverter.java create mode 100644 src/main/java/com/alibaba/excel/converters/ConverterKey.java delete mode 100644 src/main/java/com/alibaba/excel/converters/DateConverter.java delete mode 100644 src/main/java/com/alibaba/excel/converters/DoubleConverter.java delete mode 100644 src/main/java/com/alibaba/excel/converters/FloatConverter.java delete mode 100644 src/main/java/com/alibaba/excel/converters/IntegerConverter.java delete mode 100644 src/main/java/com/alibaba/excel/converters/LongConverter.java delete mode 100644 src/main/java/com/alibaba/excel/converters/StringConverter.java create mode 100644 src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java create mode 100644 src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java create mode 100644 src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java create mode 100644 src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java create mode 100644 src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java create mode 100644 src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java create mode 100644 src/main/java/com/alibaba/excel/event/NotRepeatExecutor.java create mode 100644 src/main/java/com/alibaba/excel/event/Order.java delete mode 100644 src/main/java/com/alibaba/excel/event/WriteHandler.java create mode 100644 src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java delete mode 100644 src/main/java/com/alibaba/excel/metadata/BaseRowModel.java create mode 100644 src/main/java/com/alibaba/excel/metadata/CellData.java delete mode 100644 src/main/java/com/alibaba/excel/metadata/SheetHolder.java create mode 100644 src/main/java/com/alibaba/excel/metadata/holder/ConfigurationSelector.java create mode 100644 src/main/java/com/alibaba/excel/metadata/holder/SheetHolder.java rename src/main/java/com/alibaba/excel/metadata/{ => holder}/TableHolder.java (91%) create mode 100644 src/main/java/com/alibaba/excel/metadata/holder/WorkbookHolder.java create mode 100644 src/main/java/com/alibaba/excel/util/BooleanUtils.java create mode 100644 src/main/java/com/alibaba/excel/util/DateUtils.java delete mode 100644 src/main/java/com/alibaba/excel/util/TypeUtil.java delete mode 100644 src/main/java/com/alibaba/excel/write/ExcelWriterBuilder.java create mode 100644 src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java rename src/main/java/com/alibaba/excel/write/handler/{CellExcelWriteHandler.java => CellWriteHandler.java} (82%) rename src/main/java/com/alibaba/excel/write/handler/{RowExcelWriteHandler.java => RowWriteHandler.java} (80%) rename src/main/java/com/alibaba/excel/write/handler/{SheetExcelWriteHandler.java => SheetWriteHandler.java} (80%) create mode 100644 src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java rename src/main/java/com/alibaba/excel/write/handler/{ExcelWriteHandler.java => WriteHandler.java} (73%) rename src/main/java/com/alibaba/excel/write/style/{AbstractVerticalCellStyleStrategy.java => AbstractColumnCellStyleStrategy.java} (92%) rename src/main/java/com/alibaba/excel/write/style/{HorizontalCellStyleStrategy.java => RowCellStyleStrategy.java} (57%) create mode 100644 src/test/resources/logback.xml diff --git a/pom.xml b/pom.xml index 2a06ad6..6f4cde9 100644 --- a/pom.xml +++ b/pom.xml @@ -71,13 +71,23 @@ cglib 3.1 + + org.slf4j + slf4j-api + 1.7.26 + + + ch.qos.logback + logback-classic + 1.2.3 + test + junit junit 4.12 test - diff --git a/src/main/java/com/alibaba/excel/EasyExcelFactory.java b/src/main/java/com/alibaba/excel/EasyExcelFactory.java index 758d465..7df3750 100644 --- a/src/main/java/com/alibaba/excel/EasyExcelFactory.java +++ b/src/main/java/com/alibaba/excel/EasyExcelFactory.java @@ -1,15 +1,16 @@ package com.alibaba.excel; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.event.WriteHandler; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.support.ExcelTypeEnum; - -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; /** * Reader and writer factory class @@ -69,7 +70,7 @@ public class EasyExcelFactory { * @return new ExcelWriter. */ public static ExcelWriter getWriter(OutputStream outputStream) { - return new ExcelWriter(outputStream, ExcelTypeEnum.XLSX, true); + return writerBuilder().outputFile(outputStream).build(); } /** @@ -81,7 +82,11 @@ public class EasyExcelFactory { * @return new ExcelWriter */ public static ExcelWriter getWriter(OutputStream outputStream, ExcelTypeEnum typeEnum, boolean needHead) { - return new ExcelWriter(outputStream, typeEnum, needHead); + if (needHead) { + return writerBuilder().outputFile(outputStream).excelType(typeEnum).build(); + } else { + return writerBuilder().outputFile(outputStream).excelType(typeEnum).doNotNeedHead().build(); + } } /** @@ -94,8 +99,13 @@ public class EasyExcelFactory { * @return new ExcelWriter */ public static ExcelWriter getWriterWithTemp(InputStream temp, OutputStream outputStream, ExcelTypeEnum typeEnum, - boolean needHead) { - return new ExcelWriter(temp, outputStream, typeEnum, needHead); + boolean needHead) { + if (needHead) { + return writerBuilder().withTemplate(temp).outputFile(outputStream).excelType(typeEnum).build(); + } else { + return writerBuilder().withTemplate(temp).outputFile(outputStream).excelType(typeEnum).doNotNeedHead() + .build(); + } } /** @@ -109,12 +119,26 @@ public class EasyExcelFactory { * @param handler User-defined callback * @return new ExcelWriter */ - public static ExcelWriter getWriterWithTempAndHandler(InputStream temp, - OutputStream outputStream, - ExcelTypeEnum typeEnum, - boolean needHead, - WriteHandler handler) { - return new ExcelWriter(temp, outputStream, typeEnum, needHead, handler); + public static ExcelWriter getWriterWithTempAndHandler(InputStream temp, OutputStream outputStream, + ExcelTypeEnum typeEnum, boolean needHead, WriteHandler handler) { + if (needHead) { + return writerBuilder().withTemplate(temp).outputFile(outputStream).excelType(typeEnum) + .registerWriteHandler(handler).build(); + } else { + return writerBuilder().withTemplate(temp).outputFile(outputStream).excelType(typeEnum).doNotNeedHead() + .registerWriteHandler(handler).build(); + } + } + + public static ExcelWriterBuilder writerBuilder() { + return new ExcelWriterBuilder(); } + public static ExcelWriterBuilder writerSheetBuilder() { + return new ExcelWriterBuilder(); + } + + public static ExcelWriterBuilder writerTableBuilder() { + return new ExcelWriterBuilder(); + } } diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index 652ab99..0b50857 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -2,30 +2,23 @@ package com.alibaba.excel; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.List; +import java.util.Map; -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; import com.alibaba.excel.metadata.Table; -import com.alibaba.excel.parameter.GenerateParam; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.ExcelBuilder; import com.alibaba.excel.write.ExcelBuilderImpl; -import com.alibaba.excel.write.merge.MergeStrategy; +import com.alibaba.excel.write.handler.WriteHandler; /** - * Excel Writer This tool is used to write value 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. * *
  *    1. Create a new empty Excel workbook, write the value to the stream after the value is filled.
@@ -35,103 +28,107 @@ import com.alibaba.excel.write.merge.MergeStrategy;
  * @author jipengfei
  */
 public class ExcelWriter {
-
     private ExcelBuilder excelBuilder;
 
     /**
      * Create new writer
      * 
-     * @param outputStream the java OutputStream you wish to write the value to
-     * @param typeEnum 03 or 07
+     * @param templateInputStream
+     *            Append value after a POI file ,Can be null(the template POI filesystem that contains the Workbook
+     *            stream)
+     * @param outputStream
+     *            the java OutputStream you wish to write the value to
+     * @param excelType
+     *            03 or 07
+     * @param needHead
+     * @param customConverterMap
+     * @param customWriteHandlerList
      */
-    public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum) {
-        this(outputStream, typeEnum, true);
+    public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum excelType,
+        boolean needHead, Map customConverterMap, List customWriteHandlerList) {
+        excelBuilder = new ExcelBuilderImpl(templateInputStream, outputStream, excelType, needHead, customConverterMap,
+            customWriteHandlerList);
     }
 
-    @Deprecated
-    private Class objectClass;
-
     /**
-     * @param generateParam
+     * Create new writer
+     *
+     * @param outputStream
+     *            the java OutputStream you wish to write the value to
+     * @param typeEnum
+     *            03 or 07
+     * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter
      */
     @Deprecated
-    public ExcelWriter(GenerateParam generateParam) {
-        this(generateParam.getOutputStream(), generateParam.getType(), generateParam.isNeedHead());
-        this.objectClass = generateParam.getClazz();
+    public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum) {
+        this(outputStream, typeEnum, true);
     }
 
     /**
      *
      * Create new writer
-     * 
-     * @param outputStream the java OutputStream you wish to write the value to
-     * @param typeEnum 03 or 07
-     * @param needHead Do you need to write the header to the file?
+     *
+     * @param outputStream
+     *            the java OutputStream you wish to write the value to
+     * @param typeEnum
+     *            03 or 07
+     * @param needHead
+     *            Do you need to write the header to the file?
+     * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter
      */
+    @Deprecated
     public ExcelWriter(OutputStream outputStream, ExcelTypeEnum typeEnum, boolean needHead) {
         this(null, outputStream, typeEnum, needHead, null, null);
     }
 
     /**
      * Create new writer
-     * 
-     * @param templateInputStream Append value after a POI file ,Can be null(the template POI
-     *        filesystem that contains the Workbook stream)
-     * @param outputStream the java OutputStream you wish to write the value to
-     * @param typeEnum 03 or 07
+     *
+     * @param templateInputStream
+     *            Append value after a POI file ,Can be null(the template POI filesystem that contains the Workbook
+     *            stream)
+     * @param outputStream
+     *            the java OutputStream you wish to write the value to
+     * @param typeEnum
+     *            03 or 07
+     * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter
      */
+    @Deprecated
     public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,
-                    Boolean needHead) {
+        Boolean needHead) {
         this(templateInputStream, outputStream, typeEnum, needHead, null, null);
     }
 
-
     /**
      * Create new writer
-     * 
-     * @param templateInputStream Append value after a POI file ,Can be null(the template POI
-     *        filesystem that contains the Workbook stream)
-     * @param outputStream the java OutputStream you wish to write the value to
-     * @param typeEnum 03 or 07
-     * @param writeHandler User-defined callback
+     *
+     * @param templateInputStream
+     *            Append value after a POI file ,Can be null(the template POI filesystem that contains the Workbook
+     *            stream)
+     * @param outputStream
+     *            the java OutputStream you wish to write the value to
+     * @param typeEnum
+     *            03 or 07
+     * @param writeHandler
+     *            User-defined callback
+     * @deprecated please use {@link com.alibaba.excel.write.builder.ExcelWriterBuilder} build ExcelWriter
      */
+    @Deprecated
     public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,
-                    Boolean needHead, WriteHandler writeHandler) {
-        this(templateInputStream, outputStream, typeEnum, needHead, writeHandler, null);
-    }
-
-    public ExcelWriter(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum typeEnum,
-                    Boolean needHead, WriteHandler writeHandler, List converters) {
-        excelBuilder = new ExcelBuilderImpl(templateInputStream, outputStream, typeEnum, needHead, writeHandler,
-                        converters);
-        if (this.excelBuilder instanceof ConverterRegistryCenter) {
-            ConverterRegistryCenter registryCenter = (ConverterRegistryCenter)this.excelBuilder;
-            initConverters(registryCenter, converters);
-        }
+        Boolean needHead, WriteHandler writeHandler) {
+        List customWriteHandlerList = new ArrayList();
+        customWriteHandlerList.add(writeHandler);
+        excelBuilder =
+            new ExcelBuilderImpl(templateInputStream, outputStream, typeEnum, needHead, null, customWriteHandlerList);
     }
 
-    private void initConverters(ConverterRegistryCenter registryCenter, List 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 value to a sheet
-     * 
-     * @param data Data to be written
-     * @param sheet Write to this sheet
+     * Write data to a sheet
+     *
+     * @param data
+     *            Data to be written
+     * @param sheet
+     *            Write to this sheet
      * @return this current writer
      */
     public ExcelWriter write(List data, Sheet sheet) {
@@ -139,29 +136,30 @@ public class ExcelWriter {
         return this;
     }
 
-
     /**
      * Write value to a sheet
-     * 
-     * @param data Data to be written
-     * @return this current writer
+     *
+     * @param data
+     *            Data to be written
+     * @param sheet
+     *            Write to this sheet
+     * @param table
+     *            Write to this table
+     * @return this
      */
-    @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));
-
-        }
+    public ExcelWriter write(List data, Sheet sheet, Table table) {
+        excelBuilder.addContent(data, sheet, table);
+        return this;
     }
 
     /**
      *
      * Write value to a sheet
-     * 
-     * @param data Data to be written
-     * @param sheet Write to this sheet
+     *
+     * @param data
+     *            Data to be written
+     * @param sheet
+     *            Write to this sheet
      * @return this
      */
     public ExcelWriter write1(List> data, Sheet sheet) {
@@ -171,9 +169,11 @@ public class ExcelWriter {
 
     /**
      * Write value to a sheet
-     * 
-     * @param data Data to be written
-     * @param sheet Write to this sheet
+     *
+     * @param data
+     *            Data to be written
+     * @param sheet
+     *            Write to this sheet
      * @return this
      */
     public ExcelWriter write0(List> data, Sheet sheet) {
@@ -183,23 +183,13 @@ public class ExcelWriter {
 
     /**
      * 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
-     */
-    public ExcelWriter write(List data, Sheet sheet, Table table) {
-        excelBuilder.addContent(data, sheet, table);
-        return this;
-    }
-
-    /**
-     * Write value to a sheet
-     * 
-     * @param data Data to be written
-     * @param sheet Write to this sheet
-     * @param table Write to this table
+     *
+     * @param data
+     *            Data to be written
+     * @param sheet
+     *            Write to this sheet
+     * @param table
+     *            Write to this table
      * @return this
      */
     public ExcelWriter write0(List> data, Sheet sheet, Table table) {
@@ -207,22 +197,15 @@ public class ExcelWriter {
         return this;
     }
 
-    /**
-     * Merge Cells,Indexes are zero-based.
-     *
-     * @param strategies the merge strategies.
-     */
-    public ExcelWriter merge(List strategies) {
-        excelBuilder.merge(strategies);
-        return this;
-    }
-
     /**
      * Write value to a sheet
-     * 
-     * @param data Data to be written
-     * @param sheet Write to this sheet
-     * @param table Write to this table
+     *
+     * @param data
+     *            Data to be written
+     * @param sheet
+     *            Write to this sheet
+     * @param table
+     *            Write to this table
      * @return
      */
     public ExcelWriter write1(List> data, Sheet sheet, Table table) {
@@ -236,4 +219,5 @@ public class ExcelWriter {
     public void finish() {
         excelBuilder.finish();
     }
+
 }
diff --git a/src/main/java/com/alibaba/excel/analysis/BaseSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/BaseSaxAnalyser.java
index f4decde..453e26f 100644
--- a/src/main/java/com/alibaba/excel/analysis/BaseSaxAnalyser.java
+++ b/src/main/java/com/alibaba/excel/analysis/BaseSaxAnalyser.java
@@ -1,16 +1,19 @@
 package com.alibaba.excel.analysis;
 
-import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 
 import com.alibaba.excel.context.AnalysisContext;
 import com.alibaba.excel.converters.BooleanConverter;
 import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.converters.ConverterKey;
 import com.alibaba.excel.converters.ConverterRegistryCenter;
 import com.alibaba.excel.converters.DateConverter;
+import com.alibaba.excel.converters.Double2Converter;
 import com.alibaba.excel.converters.DoubleConverter;
 import com.alibaba.excel.converters.FloatConverter;
 import com.alibaba.excel.converters.IntegerConverter;
@@ -31,9 +34,10 @@ public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, Analys
     protected AnalysisContext analysisContext;
 
     private LinkedHashMap> listeners =
-                    new LinkedHashMap>();
+        new LinkedHashMap>();
+
+    private Map converters = new HashMap();
 
-    private LinkedHashMap converters = new LinkedHashMap();
     /**
      * execute method
      */
@@ -50,13 +54,17 @@ public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, Analys
     public void register(Converter converter) {
         converters.put(converter.getName(), converter);
     }
-    
+
     @Override
     public void beforeAnalysis() {
         registerDefaultConverters();
     }
-    
+
     private void registerDefaultConverters() {
+        Double2Converter double2Converter = new Double2Converter();
+        converters.put(ConverterKey.buildConverterKey(double2Converter.supportJavaTypeKey(),
+            double2Converter.supportExcelTypeKey()), double2Converter);
+
         StringConverter s = new StringConverter();
         converters.put(s.getName(), s);
         DateConverter d = new DateConverter(this.analysisContext);
@@ -77,6 +85,7 @@ public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, Analys
     public Collection getConverters() {
         return converters.values();
     }
+
     @Override
     public void analysis(Sheet sheetParam) {
         analysisContext.setCurrentSheet(sheetParam);
@@ -92,6 +101,7 @@ public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, Analys
     public AnalysisContext getAnalysisContext() {
         return analysisContext;
     }
+
     /**
      */
     @Override
@@ -109,9 +119,9 @@ public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, Analys
     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) {
-                buildExcelHeadProperty(null, (List) analysisContext.getCurrentRowAnalysisResult());
+        if (analysisContext.getCurrentRowNum() < analysisContext.getCurrentSheet().getReadHeadRowNumber()) {
+            if (analysisContext.getCurrentRowNum() <= analysisContext.getCurrentSheet().getReadHeadRowNumber() - 1) {
+                buildExcelHeadProperty(null, (List)analysisContext.getCurrentRowAnalysisResult());
             }
         } else {
             for (Entry> entry : listeners.entrySet()) {
@@ -120,10 +130,9 @@ public abstract class BaseSaxAnalyser implements ConverterRegistryCenter, Analys
         }
     }
 
-
     private void buildExcelHeadProperty(Class clazz, List headOneRow) {
-        ExcelHeadProperty excelHeadProperty = ExcelHeadProperty
-                        .buildExcelHeadProperty(this.analysisContext.getExcelHeadProperty(), clazz, headOneRow);
+        ExcelHeadProperty excelHeadProperty =
+            ExcelHeadProperty.buildExcelHeadProperty(this.analysisContext.getExcelHeadProperty(), clazz, headOneRow);
         this.analysisContext.setExcelHeadProperty(excelHeadProperty);
     }
 }
diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java
index 6320618..6269b3b 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxRowResultHolder.java
@@ -1,11 +1,13 @@
 package com.alibaba.excel.analysis.v07;
 
+import com.alibaba.excel.metadata.CellData;
+
 public interface XlsxRowResultHolder {
     void clearResult();
     
     void appendCurrentCellValue(String currentCellValue);
-    
-    String[] getCurRowContent();
+
+    CellData[] getCurRowContent();
     
     int getColumnSize();
 }
diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java
index abce458..2135311 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/DefaultCellHandler.java
@@ -1,60 +1,61 @@
 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_FORMULA_TAG;
 import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_TAG;
+import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TAG;
 import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TAG_1;
+import static com.alibaba.excel.constant.ExcelXmlConstants.CELL_VALUE_TYPE_TAG;
 
 import java.util.Arrays;
 
+import org.apache.poi.ss.usermodel.RichTextString;
 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.enums.CellDataTypeEnum;
 import com.alibaba.excel.event.AnalysisEventRegistryCenter;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.util.BooleanUtils;
 import com.alibaba.excel.util.PositionUtils;
+import com.alibaba.excel.util.StringUtils;
 
 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;
+    private String currentTag;
+    private String currentCellIndex;
+    private int curRow;
+    private int curCol;
+    private CellData[] curRowContent = new CellData[20];
+    private CellData currentCellData;
 
-    public DefaultCellHandler(AnalysisContext analysisContext, AnalysisEventRegistryCenter registerCenter, 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];
+        curRowContent = new CellData[20];
     }
 
     @Override
     public boolean support(String name) {
-        return CELL_VALUE_TAG.equals(name) || CELL_VALUE_TAG_1.equals(name) || CELL_TAG.equals(name);
+        return CELL_VALUE_TAG.equals(name) || CELL_FORMULA_TAG.equals(name) || CELL_VALUE_TAG_1.equals(name)
+            || CELL_TAG.equals(name);
     }
 
     @Override
     public void startHandle(String name, Attributes attributes) {
+        currentTag = name;
+        // start a cell
         if (CELL_TAG.equals(name)) {
             currentCellIndex = attributes.getValue(ExcelXmlConstants.POSITION);
             int nextRow = PositionUtils.getRow(currentCellIndex);
@@ -65,51 +66,67 @@ public class DefaultCellHandler implements XlsxCellHandler, XlsxRowResultHolder
             analysisContext.setCurrentRowNum(curRow);
             curCol = PositionUtils.getCol(currentCellIndex);
 
-            String cellType = attributes.getValue("t");
-            currentCellType = FieldType.EMPTY;
-            if (cellType != null && cellType.equals("s")) {
-                currentCellType = FieldType.STRING;
-            }
+            // t="s" ,it's means String
+            // t="b" ,it's means Boolean
+            // t is null ,it's means Empty or Number
+            CellDataTypeEnum type = CellDataTypeEnum.buildFromCellType(attributes.getValue(CELL_VALUE_TYPE_TAG));
+            currentCellData = new CellData(type);
         }
-        if (name.equals(CELL_VALUE_TAG) || name.equals(CELL_VALUE_TAG_1)) {
-            // initialize current cell value
-            currentCellValue = "";
+        // cell is formula
+        if (CELL_FORMULA_TAG.equals(name)) {
+            currentCellData.setReadIsFormula(Boolean.TRUE);
         }
     }
 
     @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;
+            ensureSize();
+            // Have to go "sharedStrings.xml" and get it
+            if (currentCellData.getType() == CellDataTypeEnum.STRING) {
+                RichTextString richTextString = sst.getItemAt(Integer.parseInt(currentCellData.getStringValue()));
+                currentCellData.setStringValue(richTextString.toString());
             }
-            curRowContent[curCol] = currentCellValue;
-        } else if (CELL_VALUE_TAG_1.equals(name)) {
-            curRowContent[curCol] = currentCellValue;
+            curRowContent[curCol] = currentCellData;
         }
     }
-    
-    
 
     private void ensureSize() {
         // try to size
         if (curCol >= curRowContent.length) {
-            curRowContent = Arrays.copyOf(curRowContent, (int) (curCol * 1.5));
+            curRowContent = Arrays.copyOf(curRowContent, (int)(curCol * 1.5));
         }
     }
 
     @Override
     public void appendCurrentCellValue(String currentCellValue) {
-        this.currentCellValue += currentCellValue;
+        if (StringUtils.isEmpty(currentCellValue)) {
+            return;
+        }
+        if (CELL_FORMULA_TAG.equals(currentTag)) {
+            currentCellData.setReadFormula(currentCellValue);
+            return;
+        }
+        CellDataTypeEnum oldType = currentCellData.getType();
+        switch (oldType) {
+            case STRING:
+            case ERROR:
+                currentCellData.setStringValue(currentCellValue);
+                break;
+            case BOOLEAN:
+                currentCellData.setBooleanValue(BooleanUtils.valueOf(currentCellValue));
+                break;
+            case EMPTY:
+                currentCellData.setType(CellDataTypeEnum.NUMBER);
+                currentCellData.setDoubleValue(Double.valueOf(currentCellValue));
+                break;
+            default:
+                throw new IllegalStateException("Cannot set values now");
+        }
     }
 
     @Override
-    public String[] getCurRowContent() {
+    public CellData[] getCurRowContent() {
         return this.curRowContent;
     }
 
diff --git a/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java b/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java
index dcd2d5a..b3e7c20 100644
--- a/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java
+++ b/src/main/java/com/alibaba/excel/constant/ExcelXmlConstants.java
@@ -10,7 +10,9 @@ public class ExcelXmlConstants {
 
     public static final String ROW_TAG = "row";
     public static final String CELL_TAG = "c";
+    public static final String CELL_FORMULA_TAG = "f";
     public static final String CELL_VALUE_TAG = "v";
+    public static final String CELL_VALUE_TYPE_TAG = "t";
 
     public static final String CELL_VALUE_TAG_1 = "t";
 
diff --git a/src/main/java/com/alibaba/excel/context/WriteContext.java b/src/main/java/com/alibaba/excel/context/WriteContext.java
index 3a24606..17d978d 100644
--- a/src/main/java/com/alibaba/excel/context/WriteContext.java
+++ b/src/main/java/com/alibaba/excel/context/WriteContext.java
@@ -1,37 +1,47 @@
 package com.alibaba.excel.context;
 
-import java.io.OutputStream;
-
-import org.apache.poi.ss.usermodel.CellStyle;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
 
-import com.alibaba.excel.converters.ConverterRegistryCenter;
-import com.alibaba.excel.event.WriteHandler;
 import com.alibaba.excel.metadata.ExcelHeadProperty;
-import com.alibaba.excel.metadata.SheetHolder;
 import com.alibaba.excel.metadata.Table;
+import com.alibaba.excel.metadata.holder.ConfigurationSelector;
 
+/**
+ * Write context
+ * 
+ * @author jipengfei
+ */
 public interface WriteContext {
+    /**
+     * If the current sheet already exists, select it; if not, create it
+     * 
+     * @param sheet
+     */
+    void currentSheet(com.alibaba.excel.metadata.Sheet sheet);
 
-    Sheet getCurrentSheet();
-
-    boolean needHead();
+    /**
+     * If the current table already exists, select it; if not, create it
+     * 
+     * @param table
+     */
+    void currentTable(Table table);
 
-    ExcelHeadProperty getExcelHeadProperty();
+    /**
+     * Configuration of currently operated cell
+     * 
+     * @return
+     */
+    ConfigurationSelector configurationSelector();
 
-    void currentSheet(com.alibaba.excel.metadata.Sheet sheet);
-    
-    void currentTable(Table table);
+    Sheet getCurrentSheet();
 
-    OutputStream getOutputStream();
+    ExcelHeadProperty getExcelHeadProperty();
 
     Workbook getWorkbook();
 
-    @Deprecated
-    WriteHandler getWriteHandler();
-
-    CellStyle getCurrentContentStyle();
-    
-    ConverterRegistryCenter getConverterRegistryCenter();
+    /**
+     * close
+     */
+    void finish();
 }
diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
index d1404f7..b543b67 100644
--- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
+++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
@@ -3,28 +3,44 @@ package com.alibaba.excel.context;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 
 import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.IndexedColors;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.ss.util.CellRangeAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import com.alibaba.excel.converters.Converter;
 import com.alibaba.excel.converters.ConverterRegistryCenter;
-import com.alibaba.excel.event.WriteHandler;
+import com.alibaba.excel.converters.bigdecimal.BigDecimalNumberConverter;
+import com.alibaba.excel.converters.date.DateStringConverter;
+import com.alibaba.excel.event.NotRepeatExecutor;
+import com.alibaba.excel.event.Order;
+import com.alibaba.excel.exception.ExcelGenerateException;
+import com.alibaba.excel.metadata.CellStyle;
 import com.alibaba.excel.metadata.ExcelHeadProperty;
+import com.alibaba.excel.metadata.Font;
 import com.alibaba.excel.metadata.Head;
-import com.alibaba.excel.metadata.SheetHolder;
 import com.alibaba.excel.metadata.Table;
-import com.alibaba.excel.metadata.TableHolder;
+import com.alibaba.excel.metadata.holder.ConfigurationSelector;
+import com.alibaba.excel.metadata.holder.SheetHolder;
+import com.alibaba.excel.metadata.holder.TableHolder;
+import com.alibaba.excel.metadata.holder.WorkbookHolder;
 import com.alibaba.excel.support.ExcelTypeEnum;
-import com.alibaba.excel.util.StyleUtil;
 import com.alibaba.excel.util.WorkBookUtil;
-import com.alibaba.excel.write.style.CellStyleStrategy;
+import com.alibaba.excel.write.handler.WriteHandler;
+import com.alibaba.excel.write.style.RowCellStyleStrategy;
+import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
 
 /**
  * A context is the main anchorage point of a excel writer.
@@ -32,10 +48,13 @@ import com.alibaba.excel.write.style.CellStyleStrategy;
  * @author jipengfei
  */
 public class WriteContextImpl implements WriteContext {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(WriteContextImpl.class);
+
     /**
-     * prevent duplicate creation of sheet objects
+     * The Workbook currently written
      */
-    private final Map hasBeenInitializedSheet = new HashMap();
+    private WorkbookHolder currentWorkbookHolder;
     /**
      * Current sheet holder
      */
@@ -45,37 +64,122 @@ public class WriteContextImpl implements WriteContext {
      */
     private TableHolder currentTableHolder;
     /**
-     * Excel type
+     * Configuration of currently operated cell
      */
-    private ExcelTypeEnum excelType;
-
+    private ConfigurationSelector currentConfigurationSelector;
     /**
-     * POI Workbook
+     * Excel type
      */
-    private Workbook workbook;
-
+    private ExcelTypeEnum excelType;
     /**
      * Final output stream
      */
     private OutputStream outputStream;
-
     /**
-     * If sheet and table don't have {@link CellStyleStrategy} , use this one. If they have, use their own
+     * Final output stream
      */
-    private CellStyleStrategy defalutCellStyleStrategy;
+    private InputStream templateInputStream;
+
+    public WriteContextImpl(InputStream templateInputStream, OutputStream outputStream, ExcelTypeEnum excelType,
+        Boolean needHead, Map customConverterMap, List customWriteHandlerList) {
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Begin to Initialization 'WriteContextImpl'");
+        }
+        initCurrentWorkbookHolder(needHead, customConverterMap, customWriteHandlerList);
+        this.excelType = excelType;
+        this.outputStream = outputStream;
+        this.templateInputStream = templateInputStream;
+        try {
+            currentWorkbookHolder.setWorkbook(WorkBookUtil.createWorkBook(templateInputStream, excelType));
+        } catch (IOException e) {
+            throw new ExcelGenerateException("Create workbook failure", e);
+        }
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Initialization 'WriteContextImpl' complete");
+        }
+    }
+
+    private void initCurrentWorkbookHolder(Boolean needHead, Map customConverterMap,
+        List customWriteHandlerList) {
+        currentWorkbookHolder = new WorkbookHolder();
+        if (needHead == null) {
+            currentWorkbookHolder.setNeedHead(Boolean.TRUE);
+        } else {
+            currentWorkbookHolder.setNeedHead(needHead);
+        }
+        List handlerList = new ArrayList();
+        if (customWriteHandlerList != null && !customWriteHandlerList.isEmpty()) {
+            handlerList.addAll(customWriteHandlerList);
+        }
+        handlerList.addAll(loadDefaultHandler());
+        currentWorkbookHolder.setWriteHandlerList(sortAndClearUpHandler(handlerList));
+        Map converterMap = loadDefaultConverter();
+        if (customConverterMap != null && !customConverterMap.isEmpty()) {
+            converterMap.putAll(customConverterMap);
+        }
+        currentWorkbookHolder.setConverterMap(converterMap);
+        currentWorkbookHolder.setHasBeenInitializedSheet(new HashMap());
+        currentConfigurationSelector = currentWorkbookHolder;
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("CurrentConfigurationSelector is currentWorkbookHolder");
+        }
+    }
 
-    private WriteHandler writeHandler;
+    private List sortAndClearUpHandler(List handlerList) {
+        // sort
+        Map> orderExcelWriteHandlerMap =
+            new TreeMap>();
+        for (WriteHandler handler : handlerList) {
+            int order = Integer.MIN_VALUE;
+            if (handler instanceof Order) {
+                order = ((Order)handler).order();
+            }
+            if (orderExcelWriteHandlerMap.containsKey(order)) {
+                orderExcelWriteHandlerMap.get(order).add(handler);
+            } else {
+                List tempHandlerList = new ArrayList();
+                tempHandlerList.add(handler);
+                orderExcelWriteHandlerMap.put(order, tempHandlerList);
+            }
+        }
+        // clean up
+        Set alreadyExistedHandlerSet = new HashSet();
+        List result = new ArrayList();
+        for (Map.Entry> entry : orderExcelWriteHandlerMap.entrySet()) {
+            for (WriteHandler handler : entry.getValue()) {
+                if (handler instanceof NotRepeatExecutor) {
+                    String uniqueValue = ((NotRepeatExecutor)handler).uniqueValue();
+                    if (alreadyExistedHandlerSet.contains(uniqueValue)) {
+                        continue;
+                    }
+                    alreadyExistedHandlerSet.add(uniqueValue);
+                }
+                result.add(handler);
+            }
+        }
+        return result;
+    }
 
-    private ConverterRegistryCenter registryCenter;
+    private List loadDefaultHandler() {
+        List handlerList = new ArrayList();
+        CellStyle headCellStyle = new CellStyle();
+        Font font = new Font();
+        headCellStyle.setFont(font);
+        font.setFontName("宋体");
+        font.setBold(true);
+        headCellStyle.setIndexedColors(IndexedColors.GREY_25_PERCENT);
+        handlerList.add(new RowCellStyleStrategy(headCellStyle, new ArrayList()));
+        handlerList.add(new SimpleColumnWidthStyleStrategy(20));
+        return handlerList;
+    }
 
-    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;
+    private Map loadDefaultConverter() {
+        Map converterMap = new HashMap();
+        DateStringConverter dateStringConverter = new DateStringConverter();
+        converterMap.put(dateStringConverter.supportJavaTypeKey(), dateStringConverter);
+        BigDecimalNumberConverter bigDecimalNumberConverter = new BigDecimalNumberConverter();
+        converterMap.put(bigDecimalNumberConverter.supportJavaTypeKey(), bigDecimalNumberConverter);
+        return converterMap;
     }
 
     /**
@@ -86,83 +190,82 @@ public class WriteContextImpl implements WriteContext {
         if (sheet == null) {
             throw new IllegalArgumentException("Sheet argument cannot be null");
         }
-        if (hasBeenInitializedSheet.containsKey(sheet.getSheetNo())) {
-            currentSheetHolder = hasBeenInitializedSheet.get(sheet.getSheetNo());
-            return;
+        if (sheet.getSheetNo() == null || sheet.getSheetNo() <= 0) {
+            sheet.setSheetNo(0);
         }
-        // create sheet
-        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);
+        if (currentWorkbookHolder.getHasBeenInitializedSheet().containsKey(sheet.getSheetNo())) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Sheet:{} is already existed", sheet.getSheetNo());
             }
+            currentSheetHolder = currentWorkbookHolder.getHasBeenInitializedSheet().get(sheet.getSheetNo());
+            currentConfigurationSelector = currentSheetHolder;
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("CurrentConfigurationSelector is currentSheetHolder");
+            }
+            return;
         }
+        initCurrentSheetHolder(sheet);
         // Initialization current sheet
-        initCurrentSheet();
-    }
-
-    private void initCurrentSheet() {
-        // Initialization head
-        initExcelHeadProperty();
-        // Initialization cell style strategy
-        initCellStyleStrategy();
-        // Initialization sheet head
-        initSheetHead();
+        initCurrentSheet(sheet);
     }
 
-    private void initCellStyleStrategy() {
-        if (currentSheetParam.getCellStyleStrategy() != null) {
-            currentSheetHolder.setCellStyleStrategy(currentSheetParam.getCellStyleStrategy());
+    private void initCurrentSheetHolder(com.alibaba.excel.metadata.Sheet sheet) {
+        currentSheetHolder = new SheetHolder();
+        currentSheetHolder.setSheetParam(sheet);
+        if (sheet.getNeedHead() == null) {
+            currentSheetHolder.setNeedHead(currentConfigurationSelector.needHead());
+        } else {
+            currentSheetHolder.setNeedHead(sheet.getNeedHead());
         }
-        currentSheetHolder.setCellStyleStrategy(defalutCellStyleStrategy);
-    }
-
-    private void initTableCellStyleStrategy() {
-        if (.getCellStyleStrategy() != null) {
-            currentSheetHolder.setCellStyleStrategy(currentSheetParam.getCellStyleStrategy());
+        if (sheet.getWriteRelativeHeadRowIndex() == null) {
+            currentSheetHolder.setWriteRelativeHeadRowIndex(currentConfigurationSelector.writeRelativeHeadRowIndex());
+        } else {
+            currentSheetHolder.setNeedHead(sheet.getWriteRelativeHeadRowIndex());
         }
-        currentSheetHolder.setCellStyleStrategy(defalutCellStyleStrategy);
-    }
 
-    /**
-     * init excel header
-     */
-    private void initExcelHeadProperty() {
-        currentSheetHolder
-            .setExcelHeadProperty(new ExcelHeadProperty(currentSheetParam.getClazz(), currentSheetParam.getHead()));
-    }
+        List handlerList = new ArrayList();
+        if (sheet.getCustomWriteHandlerList() != null && !sheet.getCustomWriteHandlerList().isEmpty()) {
+            handlerList.addAll(sheet.getCustomWriteHandlerList());
+        }
+        handlerList.addAll(currentConfigurationSelector.writeHandlerList());
+        currentSheetHolder.setWriteHandlerList(sortAndClearUpHandler(handlerList));
 
-    /**
-     * init table excel header
-     */
-    private void initTableExcelHeadProperty() {
-        currentTableHolder.setExcelHeadProperty(
-            new ExcelHeadProperty(getCurrentTableParam().getClazz(), getCurrentTableParam().getHead()));
+        Map converterMap = new HashMap(currentConfigurationSelector.converterMap());
+        if (sheet.getCustomConverterMap() != null && !sheet.getCustomConverterMap().isEmpty()) {
+            converterMap.putAll(sheet.getCustomConverterMap());
+        }
+        currentWorkbookHolder.setConverterMap(converterMap);
+        currentSheetHolder.setHasBeenInitializedTable(new HashMap());
+        currentWorkbookHolder.getHasBeenInitializedSheet().put(sheet.getSheetNo(), currentSheetHolder);
+        currentConfigurationSelector = currentSheetHolder;
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("CurrentConfigurationSelector is currentSheetHolder");
+        }
     }
 
-    /**
-     * init sheet column with
-     */
-    public void initSheetColumnWidth() {
-        for (Head head : currentSheetHolder.getExcelHeadProperty().getHeadList()) {
-            currentSheet.setColumnWidth(head.getColumnIndex(), currentSheetHolder.getColumnWidthStyleStrategy()
-                .columnWidth(head.getColumnIndex(), head.getFieldName()));
+    private void initCurrentSheet(com.alibaba.excel.metadata.Sheet sheet) {
+        Sheet currentSheet;
+        try {
+            currentSheet = currentWorkbookHolder.getWorkbook().getSheetAt(sheet.getSheetNo());
+        } catch (Exception e) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.info("Can not find sheet:{} ,now create it", sheet.getSheetNo());
+            }
+            currentSheet = WorkBookUtil.createSheet(currentWorkbookHolder.getWorkbook(), sheet);
         }
+        currentSheetHolder.setSheet(currentSheet);
+        // Initialization head
+        currentSheetHolder.setExcelHeadProperty(new ExcelHeadProperty(sheet.getClazz(), sheet.getHead()));
+        // Initialization head
+        initHead();
     }
 
-    public void initSheetHead() {
-        if (!currentSheetHolder.isNeedHead() || !currentSheetHolder.getExcelHeadProperty().hasHead()) {
+    public void initHead(ExcelHeadProperty excelHeadPropert) {
+        if (!currentConfigurationSelector.needHead() || !currentSheetHolder.getExcelHeadProperty().hasHead()) {
             return;
         }
         int startRow = getCurrentSheet().getLastRowNum();
-        if (startRow > 0) {
-            startRow += 4;
-        } else {
-            startRow = getCurrentSheetParam().getStartRow();
-        }
+        startRow += currentConfigurationSelector.writeRelativeHeadRowIndex();
         // Combined head
         addMergedRegionToCurrentSheet(startRow);
         for (int i = startRow; i < currentSheetHolder.getExcelHeadProperty().getHeadRowNumber() + startRow; i++) {
@@ -174,8 +277,6 @@ public class WriteContextImpl implements WriteContext {
             }
             addOneRowOfHeadDataToExcel(row, i, currentSheetHolder.getExcelHeadProperty().getHeadList());
         }
-        // Initialization sheet column width
-        initSheetColumnWidth();
     }
 
     public void initTableHead() {
@@ -270,15 +371,6 @@ public class WriteContextImpl implements WriteContext {
         return this.needHead;
     }
 
-    @Override
-    public Sheet getCurrentSheet() {
-        return currentSheetHolder.getSheet();
-    }
-
-    public void setCurrentSheet(Sheet currentSheet) {
-        this.currentSheet = currentSheet;
-    }
-
     public String getCurrentSheetName() {
         return currentSheetHolder.getCurrentSheetParam();
     }
@@ -333,4 +425,20 @@ public class WriteContextImpl implements WriteContext {
     public ConverterRegistryCenter getConverterRegistryCenter() {
         return registryCenter;
     }
+
+    @Override
+    public void finish() {
+        try {
+            workbook.write(outputStream);
+            workbook.close();
+            if (outputStream != null) {
+                outputStream.close();
+            }
+            if (templateInputStream != null) {
+                templateInputStream.close();
+            }
+        } catch (IOException e) {
+            throw new ExcelGenerateException("Can not close IO", e);
+        }
+    }
 }
diff --git a/src/main/java/com/alibaba/excel/converters/BigDecimalConverter.java b/src/main/java/com/alibaba/excel/converters/BigDecimalConverter.java
deleted file mode 100644
index feee369..0000000
--- a/src/main/java/com/alibaba/excel/converters/BigDecimalConverter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-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;
-    }
-    
-}
diff --git a/src/main/java/com/alibaba/excel/converters/BooleanConverter.java b/src/main/java/com/alibaba/excel/converters/BooleanConverter.java
deleted file mode 100644
index bca16d7..0000000
--- a/src/main/java/com/alibaba/excel/converters/BooleanConverter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-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());
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/converters/Converter.java b/src/main/java/com/alibaba/excel/converters/Converter.java
index 11bbcdb..7a9a11b 100644
--- a/src/main/java/com/alibaba/excel/converters/Converter.java
+++ b/src/main/java/com/alibaba/excel/converters/Converter.java
@@ -1,13 +1,17 @@
 package com.alibaba.excel.converters;
 
-import org.apache.poi.ss.usermodel.Cell;
-
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
 import com.alibaba.excel.metadata.ExcelColumnProperty;
+import com.sun.istack.internal.NotNull;
+
+public interface Converter {
+
+    Class supportJavaTypeKey();
+
+    CellDataTypeEnum supportExcelTypeKey();
+
+    T convertToJavaData(@NotNull CellData cellData, ExcelColumnProperty columnProperty) throws Exception;
 
-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);
+    CellData convertToExcelData(@NotNull T value, ExcelColumnProperty columnProperty) throws Exception;
 }
diff --git a/src/main/java/com/alibaba/excel/converters/ConverterKey.java b/src/main/java/com/alibaba/excel/converters/ConverterKey.java
new file mode 100644
index 0000000..037ba81
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/converters/ConverterKey.java
@@ -0,0 +1,48 @@
+package com.alibaba.excel.converters;
+
+import com.alibaba.excel.enums.CellDataTypeEnum;
+
+/**
+ * Converter unique key
+ * 
+ * @author zhuangjiaju
+ */
+public class ConverterKey {
+
+    private Class javaTypeKey;
+    private CellDataTypeEnum excelTypeKey;
+
+    public ConverterKey(Class javaTypeKey, CellDataTypeEnum excelTypeKey) {
+        if (javaTypeKey == null || excelTypeKey == null) {
+            throw new IllegalArgumentException("All parameters can not be null");
+        }
+        this.javaTypeKey = javaTypeKey;
+        this.excelTypeKey = excelTypeKey;
+    }
+
+    public static ConverterKey buildConverterKey(Class javaTypeKey, CellDataTypeEnum excelTypeKey) {
+        return new ConverterKey(javaTypeKey, excelTypeKey);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        ConverterKey that = (ConverterKey)o;
+        if (javaTypeKey != null ? !javaTypeKey.equals(that.javaTypeKey) : that.javaTypeKey != null) {
+            return false;
+        }
+        return excelTypeKey == that.excelTypeKey;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = javaTypeKey != null ? javaTypeKey.hashCode() : 0;
+        result = 31 * result + (excelTypeKey != null ? excelTypeKey.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/converters/DateConverter.java b/src/main/java/com/alibaba/excel/converters/DateConverter.java
deleted file mode 100644
index 40f9abe..0000000
--- a/src/main/java/com/alibaba/excel/converters/DateConverter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-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;
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/converters/DoubleConverter.java b/src/main/java/com/alibaba/excel/converters/DoubleConverter.java
deleted file mode 100644
index 27efbb6..0000000
--- a/src/main/java/com/alibaba/excel/converters/DoubleConverter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-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());
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/converters/FloatConverter.java b/src/main/java/com/alibaba/excel/converters/FloatConverter.java
deleted file mode 100644
index 5c17c62..0000000
--- a/src/main/java/com/alibaba/excel/converters/FloatConverter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-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());
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/converters/IntegerConverter.java b/src/main/java/com/alibaba/excel/converters/IntegerConverter.java
deleted file mode 100644
index 6433992..0000000
--- a/src/main/java/com/alibaba/excel/converters/IntegerConverter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-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());
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/converters/LongConverter.java b/src/main/java/com/alibaba/excel/converters/LongConverter.java
deleted file mode 100644
index 36245a1..0000000
--- a/src/main/java/com/alibaba/excel/converters/LongConverter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-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());
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/converters/StringConverter.java b/src/main/java/com/alibaba/excel/converters/StringConverter.java
deleted file mode 100644
index 281ffaf..0000000
--- a/src/main/java/com/alibaba/excel/converters/StringConverter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-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;
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java
new file mode 100644
index 0000000..ac3453b
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalBooleanConverter.java
@@ -0,0 +1,42 @@
+package com.alibaba.excel.converters.bigdecimal;
+
+import java.math.BigDecimal;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.ExcelColumnProperty;
+
+/**
+ * BigDecimal and boolean converter
+ *
+ * @author zhuangjiaju
+ */
+public class BigDecimalBooleanConverter implements Converter {
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return BigDecimal.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.BOOLEAN;
+    }
+
+    @Override
+    public BigDecimal convertToJavaData(CellData cellData, ExcelColumnProperty columnProperty) {
+        if (cellData.getBooleanValue()) {
+            return BigDecimal.ONE;
+        }
+        return BigDecimal.ZERO;
+    }
+
+    @Override
+    public CellData convertToExcelData(BigDecimal value, ExcelColumnProperty columnProperty) {
+        if (BigDecimal.ONE.equals(value)) {
+            return new CellData(Boolean.TRUE);
+        }
+        return new CellData(Boolean.FALSE);
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java
new file mode 100644
index 0000000..09ef24c
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalNumberConverter.java
@@ -0,0 +1,36 @@
+package com.alibaba.excel.converters.bigdecimal;
+
+import java.math.BigDecimal;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.ExcelColumnProperty;
+
+/**
+ * BigDecimal and number converter
+ *
+ * @author zhuangjiaju
+ */
+public class BigDecimalNumberConverter implements Converter {
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return BigDecimal.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.NUMBER;
+    }
+
+    @Override
+    public BigDecimal convertToJavaData(CellData cellData, ExcelColumnProperty columnProperty) {
+        return new BigDecimal(cellData.getDoubleValue());
+    }
+
+    @Override
+    public CellData convertToExcelData(BigDecimal value, ExcelColumnProperty columnProperty) {
+        return new CellData(value.doubleValue());
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java
new file mode 100644
index 0000000..2e327c4
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/converters/bigdecimal/BigDecimalStringConverter.java
@@ -0,0 +1,41 @@
+package com.alibaba.excel.converters.bigdecimal;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.ExcelColumnProperty;
+import com.alibaba.excel.util.StringUtils;
+
+/**
+ * BigDecimal and string converter
+ *
+ * @author zhuangjiaju
+ */
+public class BigDecimalStringConverter implements Converter {
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return BigDecimal.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    @Override
+    public BigDecimal convertToJavaData(CellData cellData, ExcelColumnProperty columnProperty) {
+        return new BigDecimal(cellData.getStringValue());
+    }
+
+    @Override
+    public CellData convertToExcelData(BigDecimal value, ExcelColumnProperty columnProperty) {
+        if (StringUtils.isEmpty(columnProperty.getFormat())) {
+            return new CellData(value.toString());
+        }
+        return new CellData(new DecimalFormat(columnProperty.getFormat()).format(value));
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java b/src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java
new file mode 100644
index 0000000..e784e60
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/converters/date/DateNumberConverter.java
@@ -0,0 +1,39 @@
+package com.alibaba.excel.converters.date;
+
+import java.util.Date;
+
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.ExcelColumnProperty;
+
+/**
+ * Date and number converter
+ * 
+ * @author zhuangjiaju
+ */
+public class DateNumberConverter implements Converter {
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return Date.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.NUMBER;
+    }
+
+    @Override
+    public Date convertToJavaData(CellData cellData, ExcelColumnProperty columnProperty) {
+        return HSSFDateUtil.getJavaDate(cellData.getDoubleValue(), columnProperty.getUse1904windowing(),
+            columnProperty.getTimeZone());
+    }
+
+    @Override
+    public CellData convertToExcelData(Date value, ExcelColumnProperty columnProperty) {
+        return new CellData((double)(value.getTime()));
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java b/src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java
new file mode 100644
index 0000000..f346c4c
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/converters/date/DateStringConverter.java
@@ -0,0 +1,37 @@
+package com.alibaba.excel.converters.date;
+
+import java.text.ParseException;
+import java.util.Date;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.ExcelColumnProperty;
+import com.alibaba.excel.util.DateUtils;
+
+/**
+ * Date and string converter
+ *
+ * @author zhuangjiaju
+ */
+public class DateStringConverter implements Converter {
+    @Override
+    public Class supportJavaTypeKey() {
+        return Date.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    @Override
+    public Date convertToJavaData(CellData cellData, ExcelColumnProperty columnProperty) throws ParseException {
+        return DateUtils.parseDate(cellData.getStringValue(), columnProperty.getFormat());
+    }
+
+    @Override
+    public CellData convertToExcelData(Date value, ExcelColumnProperty columnProperty) {
+        return new CellData(DateUtils.format(value, columnProperty.getFormat()));
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java b/src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java
new file mode 100644
index 0000000..0081c2f
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/enums/CellDataTypeEnum.java
@@ -0,0 +1,54 @@
+package com.alibaba.excel.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.alibaba.excel.util.StringUtils;
+
+/**
+ * excel internal data type
+ *
+ * @author zhuangjiaju
+ */
+public enum CellDataTypeEnum {
+    /**
+     * string
+     */
+    STRING,
+    /**
+     * number
+     */
+    NUMBER,
+    /**
+     * boolean
+     */
+    BOOLEAN,
+    /**
+     * empty
+     */
+    EMPTY,
+    /**
+     * error
+     */
+    ERROR;
+
+    private static final Map TYPE_ROUTING_MAP = new HashMap(8);
+    static {
+        TYPE_ROUTING_MAP.put("s", STRING);
+        TYPE_ROUTING_MAP.put("e", ERROR);
+        TYPE_ROUTING_MAP.put("b", BOOLEAN);
+    }
+
+    /**
+     * Build data types
+     * 
+     * @param cellType
+     * @return
+     */
+    public static CellDataTypeEnum buildFromCellType(String cellType) {
+        if (StringUtils.isEmpty(cellType)) {
+            return EMPTY;
+        }
+        return TYPE_ROUTING_MAP.get(cellType);
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/enums/HeadKindEnum.java b/src/main/java/com/alibaba/excel/enums/HeadKindEnum.java
index e7f19d9..e9e5b65 100644
--- a/src/main/java/com/alibaba/excel/enums/HeadKindEnum.java
+++ b/src/main/java/com/alibaba/excel/enums/HeadKindEnum.java
@@ -1,7 +1,7 @@
 package com.alibaba.excel.enums;
 
 /**
- * The types of head
+ * The types of header
  *
  * @author zhuangjiaju
  **/
diff --git a/src/main/java/com/alibaba/excel/event/EachRowAnalysisFinishEvent.java b/src/main/java/com/alibaba/excel/event/EachRowAnalysisFinishEvent.java
index 9a31ef4..9173caa 100644
--- a/src/main/java/com/alibaba/excel/event/EachRowAnalysisFinishEvent.java
+++ b/src/main/java/com/alibaba/excel/event/EachRowAnalysisFinishEvent.java
@@ -3,6 +3,8 @@ package com.alibaba.excel.event;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.alibaba.excel.metadata.CellData;
+
 /**
  * @author jipengfei
  */
@@ -12,9 +14,9 @@ public class EachRowAnalysisFinishEvent implements AnalysisFinishEvent {
         this.result = content;
     }
 
-    public EachRowAnalysisFinishEvent(String[] content, int length) {
+    public EachRowAnalysisFinishEvent(CellData[] content, int length) {
         if (content != null) {
-            List ls = new ArrayList(length);
+            List ls = new ArrayList(length);
             for (int i = 0; i <= length; i++) {
                 ls.add(content[i]);
             }
diff --git a/src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java b/src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java
index 82f7708..193af9d 100644
--- a/src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java
+++ b/src/main/java/com/alibaba/excel/event/ModelBuildEventListener.java
@@ -9,6 +9,7 @@ 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.CellData;
 import com.alibaba.excel.metadata.ExcelColumnProperty;
 import com.alibaba.excel.metadata.ExcelHeadProperty;
 import com.alibaba.excel.util.TypeUtil;
@@ -29,7 +30,7 @@ public class ModelBuildEventListener extends AnalysisEventListener {
         if (context.getExcelHeadProperty() != null && context.getExcelHeadProperty().getHeadClazz() != null) {
             try {
                 @SuppressWarnings("unchecked")
-                Object resultModel = buildUserModel(context, (List)object);
+                Object resultModel = buildUserModel(context, (List)object);
                 context.setCurrentRowAnalysisResult(resultModel);
             } catch (Exception e) {
                 throw new ExcelGenerateException(e);
@@ -38,7 +39,7 @@ public class ModelBuildEventListener extends AnalysisEventListener {
     }
 
     @SuppressWarnings({"rawtypes", "unchecked"})
-    private Object buildUserModel(AnalysisContext context, List stringList) throws Exception {
+    private Object buildUserModel(AnalysisContext context, List cellDataList) throws Exception {
         ExcelHeadProperty excelHeadProperty = context.getExcelHeadProperty();
         Object resultModel = excelHeadProperty.getHeadClazz().newInstance();
         if (excelHeadProperty == null) {
@@ -58,8 +59,14 @@ public class ModelBuildEventListener extends AnalysisEventListener {
         return resultModel;
     }
 
-    private Object convertValue(String value, ExcelColumnProperty columnProperty) {
+    private Object convertValue(CellData cellData, ExcelColumnProperty columnProperty) {
+
+//        columnProperty.getField().getClass(), cellData.getType();
+
+
         for (Converter c : converters) {
+//            c.convertToJavaData(cellData,columnProperty);
+
             if (c.support(columnProperty)) {
                 return c.convert(value, columnProperty);
             }
diff --git a/src/main/java/com/alibaba/excel/event/NotRepeatExecutor.java b/src/main/java/com/alibaba/excel/event/NotRepeatExecutor.java
new file mode 100644
index 0000000..51f3113
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/event/NotRepeatExecutor.java
@@ -0,0 +1,16 @@
+package com.alibaba.excel.event;
+
+/**
+ * There are multiple interceptors that execute only one of them when fired once.If you want to control which one to
+ * execute please use {@link Order}
+ *
+ * @author zhuangjiaju
+ **/
+public interface NotRepeatExecutor {
+    /**
+     * To see if it's the same executor
+     * 
+     * @return
+     */
+    String uniqueValue();
+}
diff --git a/src/main/java/com/alibaba/excel/event/Order.java b/src/main/java/com/alibaba/excel/event/Order.java
new file mode 100644
index 0000000..a20cd48
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/event/Order.java
@@ -0,0 +1,15 @@
+package com.alibaba.excel.event;
+
+/**
+ * Implement this interface when sorting
+ * 
+ * @author zhuangjiaju
+ */
+public interface Order {
+    /**
+     * The smaller the first implementation
+     *
+     * @return
+     */
+    int order();
+}
diff --git a/src/main/java/com/alibaba/excel/event/WriteHandler.java b/src/main/java/com/alibaba/excel/event/WriteHandler.java
deleted file mode 100644
index 1927f63..0000000
--- a/src/main/java/com/alibaba/excel/event/WriteHandler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.alibaba.excel.event;
-
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-
-import com.alibaba.excel.write.handler.ExcelWriteHandler;
-
-/**
- *
- * @deprecated Separate implementations
- * @see com.alibaba.excel.write.handler.SheetExcelWriteHandler
- * @see com.alibaba.excel.write.handler.RowExcelWriteHandler
- * @see com.alibaba.excel.write.handler.CellExcelWriteHandler
- * @author jipengfei
- */
-public interface WriteHandler extends ExcelWriteHandler {
-
-    /**
-     * Custom operation after creating each sheet
-     *
-     * @param sheetNo
-     * @param sheet
-     */
-    void sheet(int sheetNo, Sheet sheet);
-
-    /**
-     * Custom operation after creating each row
-     *
-     * @param rowNum
-     * @param row
-     */
-    void row(int rowNum, Row row);
-
-    /**
-     * Custom operation after creating each cell
-     * 
-     * @param cellNum
-     * @param cell
-     */
-    void cell(int cellNum, Cell cell);
-}
diff --git a/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java b/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java
new file mode 100644
index 0000000..5c5fb12
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/exception/ExcelDataConvertException.java
@@ -0,0 +1,21 @@
+package com.alibaba.excel.exception;
+
+/**
+ * Data convert exception
+ * 
+ * @author zhuangjiaju
+ */
+public class ExcelDataConvertException extends RuntimeException {
+
+    public ExcelDataConvertException(String message) {
+        super(message);
+    }
+
+    public ExcelDataConvertException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ExcelDataConvertException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/metadata/BaseRowModel.java b/src/main/java/com/alibaba/excel/metadata/BaseRowModel.java
deleted file mode 100644
index 6f4a805..0000000
--- a/src/main/java/com/alibaba/excel/metadata/BaseRowModel.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.alibaba.excel.metadata;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.poi.ss.usermodel.CellStyle;
-
-/**
- * Excel基础模型
- * @author jipengfei
- */
-public class BaseRowModel {
-
-    /**
-     * 每列样式
-     */
-    private Map cellStyleMap = new HashMap();
-
-    public void addStyle(Integer row, CellStyle cellStyle){
-        cellStyleMap.put(row,cellStyle);
-    }
-
-    public CellStyle getStyle(Integer row){
-        return cellStyleMap.get(row);
-    }
-
-    public Map getCellStyleMap() {
-        return cellStyleMap;
-    }
-
-    public void setCellStyleMap(Map cellStyleMap) {
-        this.cellStyleMap = cellStyleMap;
-    }
-}
diff --git a/src/main/java/com/alibaba/excel/metadata/CellData.java b/src/main/java/com/alibaba/excel/metadata/CellData.java
new file mode 100644
index 0000000..8920c92
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/metadata/CellData.java
@@ -0,0 +1,138 @@
+package com.alibaba.excel.metadata;
+
+import com.alibaba.excel.enums.CellDataTypeEnum;
+
+/**
+ * excel internal cell data
+ *
+ * @author zhuangjiaju
+ */
+public class CellData {
+    private CellDataTypeEnum type;
+    /**
+     * {@link CellDataTypeEnum#NUMBER}
+     */
+    private Double doubleValue;
+    /**
+     * {@link CellDataTypeEnum#STRING} and{@link CellDataTypeEnum#ERROR}
+     */
+    private String stringValue;
+    /**
+     * {@link CellDataTypeEnum#BOOLEAN}
+     */
+    private Boolean booleanValue;
+
+    /**
+     * Support only when reading
+     */
+    private Boolean readIsFormula;
+    /**
+     * Support only when reading
+     */
+    private String readFormula;
+
+    public CellData(String stringValue) {
+        this(CellDataTypeEnum.STRING, stringValue);
+    }
+
+    public CellData(CellDataTypeEnum type, String stringValue) {
+        if (type != CellDataTypeEnum.STRING && type != CellDataTypeEnum.ERROR) {
+            throw new IllegalArgumentException("Only support CellDataTypeEnum.STRING and  CellDataTypeEnum.ERROR");
+        }
+        if (stringValue == null) {
+            throw new IllegalArgumentException("StringValue can not be null");
+        }
+        this.type = type;
+        this.stringValue = stringValue;
+        this.readIsFormula = Boolean.FALSE;
+    }
+
+    public CellData(Double doubleValue) {
+        if (doubleValue == null) {
+            throw new IllegalArgumentException("DoubleValue can not be null");
+        }
+        this.type = CellDataTypeEnum.NUMBER;
+        this.doubleValue = doubleValue;
+        this.readIsFormula = Boolean.FALSE;
+    }
+
+    public CellData(Boolean booleanValue) {
+        if (booleanValue == null) {
+            throw new IllegalArgumentException("BooleanValue can not be null");
+        }
+        this.type = CellDataTypeEnum.BOOLEAN;
+        this.booleanValue = booleanValue;
+        this.readIsFormula = Boolean.FALSE;
+    }
+
+    public CellData(CellDataTypeEnum type) {
+        if (type == null) {
+            throw new IllegalArgumentException("Type can not be null");
+        }
+        this.type = type;
+        this.readIsFormula = Boolean.FALSE;
+    }
+
+    public CellDataTypeEnum getType() {
+        return type;
+    }
+
+    public void setType(CellDataTypeEnum type) {
+        this.type = type;
+    }
+
+    public Double getDoubleValue() {
+        return doubleValue;
+    }
+
+    public void setDoubleValue(Double doubleValue) {
+        this.doubleValue = doubleValue;
+    }
+
+    public String getStringValue() {
+        return stringValue;
+    }
+
+    public void setStringValue(String stringValue) {
+        this.stringValue = stringValue;
+    }
+
+    public Boolean getBooleanValue() {
+        return booleanValue;
+    }
+
+    public void setBooleanValue(Boolean booleanValue) {
+        this.booleanValue = booleanValue;
+    }
+
+    public Boolean getReadIsFormula() {
+        return readIsFormula;
+    }
+
+    public void setReadIsFormula(Boolean readIsFormula) {
+        this.readIsFormula = readIsFormula;
+    }
+
+    public String getReadFormula() {
+        return readFormula;
+    }
+
+    public void setReadFormula(String readFormula) {
+        this.readFormula = readFormula;
+    }
+
+    @Override
+    public String toString() {
+        switch (type) {
+            case NUMBER:
+                return doubleValue.toString();
+            case BOOLEAN:
+                return booleanValue.toString();
+            case STRING:
+            case ERROR:
+                return stringValue;
+            default:
+                return "empty";
+        }
+    }
+}
diff --git a/src/main/java/com/alibaba/excel/metadata/CellStyle.java b/src/main/java/com/alibaba/excel/metadata/CellStyle.java
index 62a42ea..0d119aa 100644
--- a/src/main/java/com/alibaba/excel/metadata/CellStyle.java
+++ b/src/main/java/com/alibaba/excel/metadata/CellStyle.java
@@ -12,11 +12,10 @@ public class CellStyle {
      * 表头背景颜色
      */
     private IndexedColors indexedColors;
-
     /**
      * 表头字体样式
      */
-    private Font simpleFont;
+    private Font font;
 
     public IndexedColors getIndexedColors() {
         return indexedColors;
@@ -26,11 +25,11 @@ public class CellStyle {
         this.indexedColors = indexedColors;
     }
 
-    public Font getSimpleFont() {
-        return simpleFont;
+    public Font getFont() {
+        return font;
     }
 
-    public void setSimpleFont(Font simpleFont) {
-        this.simpleFont = simpleFont;
+    public void setFont(Font font) {
+        this.font = font;
     }
 }
diff --git a/src/main/java/com/alibaba/excel/metadata/ExcelColumnProperty.java b/src/main/java/com/alibaba/excel/metadata/ExcelColumnProperty.java
index cc6442f..bfecc6d 100644
--- a/src/main/java/com/alibaba/excel/metadata/ExcelColumnProperty.java
+++ b/src/main/java/com/alibaba/excel/metadata/ExcelColumnProperty.java
@@ -3,6 +3,7 @@ package com.alibaba.excel.metadata;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.TimeZone;
 
 /**
  * @author jipengfei
@@ -22,9 +23,30 @@ public class ExcelColumnProperty implements Comparable {
     private List head = new ArrayList();
 
     /**
+     *
      */
     private String format;
 
+    private Boolean use1904windowing;
+
+    private TimeZone timeZone;
+
+    public Boolean getUse1904windowing() {
+        return use1904windowing;
+    }
+
+    public void setUse1904windowing(Boolean use1904windowing) {
+        this.use1904windowing = use1904windowing;
+    }
+
+    public TimeZone getTimeZone() {
+        return timeZone;
+    }
+
+    public void setTimeZone(TimeZone timeZone) {
+        this.timeZone = timeZone;
+    }
+
     public String getFormat() {
         return format;
     }
@@ -62,4 +84,4 @@ public class ExcelColumnProperty implements Comparable {
         int y = o.getIndex();
         return (x < y) ? -1 : ((x == y) ? 0 : 1);
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java b/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java
index 354b17d..2e8fc19 100644
--- a/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java
+++ b/src/main/java/com/alibaba/excel/metadata/ExcelHeadProperty.java
@@ -22,7 +22,7 @@ public class ExcelHeadProperty {
     /**
      * Custom class
      */
-    private Class headClazz;
+    private Class headClazz;
 
     /**
      * A two-dimensional array describing the header
@@ -47,7 +47,7 @@ public class ExcelHeadProperty {
      */
     private int headRowNumber;
 
-    public ExcelHeadProperty(Class headClazz, List> head) {
+    public ExcelHeadProperty(Class headClazz, List> head) {
         this.headClazz = headClazz;
         headList = new ArrayList();
         headKind = HeadKindEnum.NONE;
@@ -67,7 +67,7 @@ public class ExcelHeadProperty {
     }
 
     public static ExcelHeadProperty buildExcelHeadProperty(ExcelHeadProperty excelHeadProperty,
-        Class clazz, List headOneRow) {
+        Class clazz, List headOneRow) {
         if (excelHeadProperty == null) {
             return new ExcelHeadProperty(clazz, new ArrayList>());
         }
@@ -80,7 +80,7 @@ public class ExcelHeadProperty {
     private void initHeadRowNumber() {
         headRowNumber = 0;
         for (Head head : headList) {
-            List list = head.getHeadNames();
+            List list = head.getHeadNameList();
             if (list != null && list.size() > headRowNumber) {
                 headRowNumber = list.size();
             }
@@ -156,7 +156,7 @@ public class ExcelHeadProperty {
             String rowData = row.get(i);
             // join
             if (i <= headSize) {
-                headList.get(i).getHeadNames().add(rowData);
+                headList.get(i).getHeadNameList().add(rowData);
             } else {
                 // create and join
                 headList.add(new Head(i, null, rowData));
@@ -173,11 +173,11 @@ public class ExcelHeadProperty {
         return excelColumnPropertyMap1.get(columnNum);
     }
 
-    public Class getHeadClazz() {
+    public Class getHeadClazz() {
         return headClazz;
     }
 
-    public void setHeadClazz(Class headClazz) {
+    public void setHeadClazz(Class headClazz) {
         this.headClazz = headClazz;
     }
 
@@ -225,7 +225,7 @@ public class ExcelHeadProperty {
     public List getCellRangeModels() {
         List cellRanges = new ArrayList();
         for (int i = 0; i < headList.size(); i++) {
-            List columnValues = headList.get(i).getHeadNames();
+            List columnValues = headList.get(i).getHeadNameList();
             for (int j = 0; j < columnValues.size(); j++) {
                 int lastRow = getLastRangNum(j, columnValues.get(j), columnValues);
                 int lastColumn = getLastRangNum(i, columnValues.get(j), getHeadByRowNum(j));
@@ -240,7 +240,7 @@ public class ExcelHeadProperty {
     public List getHeadByRowNum(int rowNum) {
         List l = new ArrayList(headList.size());
         for (Head head : headList) {
-            List list = head.getHeadNames();
+            List list = head.getHeadNameList();
             if (list.size() > rowNum) {
                 l.add(list.get(rowNum));
             } else {
diff --git a/src/main/java/com/alibaba/excel/metadata/Head.java b/src/main/java/com/alibaba/excel/metadata/Head.java
index d88d038..5c10e75 100644
--- a/src/main/java/com/alibaba/excel/metadata/Head.java
+++ b/src/main/java/com/alibaba/excel/metadata/Head.java
@@ -9,25 +9,33 @@ import java.util.List;
  * @author zhuangjiaju
  **/
 public class Head {
+    /**
+     * Column index of head
+     */
     private Integer columnIndex;
+    /**
+     * It only has values when passed in {@link Sheet#setClazz(Class)} and {@link Table#setClazz(Class)}
+     */
     private String fieldName;
-    private List headNames;
+    /**
+     * Head name
+     */
+    private List headNameList;
 
     public Head(Integer columnIndex, String fieldName, String headName) {
         this.columnIndex = columnIndex;
         this.fieldName = fieldName;
-        List headNamesTmp = new ArrayList();
-        headNamesTmp.add(headName);
-        this.headNames = headNamesTmp;
+        headNameList = new ArrayList();
+        headNameList.add(headName);
     }
 
-    public Head(Integer columnIndex, String fieldName, List headNames) {
+    public Head(Integer columnIndex, String fieldName, List headNameList) {
         this.columnIndex = columnIndex;
         this.fieldName = fieldName;
-        if (headNames == null) {
-            headNames = new ArrayList();
+        if (headNameList == null) {
+            headNameList = new ArrayList();
         }
-        this.headNames = headNames;
+        this.headNameList = headNameList;
     }
 
     public Integer getColumnIndex() {
@@ -46,12 +54,18 @@ public class Head {
         this.fieldName = fieldName;
     }
 
-    public List getHeadNames() {
-        return headNames;
+    public List getHeadNameList() {
+        return headNameList;
+    }
+
+    public void setHeadNameList(List headNameList) {
+        this.headNameList = headNameList;
     }
 
-    public void setHeadNames(List headNames) {
-        this.headNames = headNames;
+    @Override
+    public String toString() {
+        return "Head{" + "columnIndex=" + columnIndex + ", fieldName='" + fieldName + '\'' + ", headNameList="
+            + headNameList + '}';
     }
 
     /**
@@ -61,13 +75,13 @@ public class Head {
      * @return
      */
     public String getHeadName(int index) {
-        if (headNames == null || headNames.isEmpty()) {
+        if (headNameList == null || headNameList.isEmpty()) {
             return null;
         }
-        if (index >= headNames.size()) {
-            return headNames.get(headNames.size() - 1);
+        if (index >= headNameList.size()) {
+            return headNameList.get(headNameList.size() - 1);
         } else {
-            return headNames.get(index);
+            return headNameList.get(index);
         }
     }
 }
diff --git a/src/main/java/com/alibaba/excel/metadata/Sheet.java b/src/main/java/com/alibaba/excel/metadata/Sheet.java
index 8aaa076..d8cf0e4 100644
--- a/src/main/java/com/alibaba/excel/metadata/Sheet.java
+++ b/src/main/java/com/alibaba/excel/metadata/Sheet.java
@@ -1,99 +1,89 @@
 package com.alibaba.excel.metadata;
 
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.poi.ss.usermodel.TableStyle;
-
-import com.alibaba.excel.write.style.CellStyleStrategy;
-import com.alibaba.excel.write.style.column.ColumnWihtStyleStrategy;
-import com.alibaba.excel.write.style.column.ColumnWithStyleStrategy;
-import com.oracle.webservices.internal.api.databinding.DatabindingMode;
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.write.handler.WriteHandler;
 
 /**
- *
+ * sheet
+ * 
  * @author jipengfei
  */
 public class Sheet {
-
     /**
+     * Starting from 0
      */
-    private int headLineMun;
-
+    private Integer sheetNo;
     /**
-     * Starting from 1
+     * sheet name
      */
-    private int sheetNo;
-
+    private String sheetName;
     /**
+     * Count the number of added heads when read sheet.
+     *
+     * 
  • 0 - This Sheet has no head ,since the first row are the data + *
  • 1 - This Sheet has one row head , this is the default + *
  • 2 - This Sheet has two row head ,since the third row is the data */ - private String sheetName; + private Integer readHeadRowNumber; /** + * Writes the head relative to the existing contents of the sheet. Indexes are zero-based. */ - private Class clazz; - + private Integer writeRelativeHeadRowIndex; /** + * You can only choose one of the {@link Sheet#head} and {@link Sheet#clazz} */ private List> head; - /** - * + * You can only choose one of the {@link Sheet#head} and {@link Sheet#clazz} */ - @Deprecated - private TableStyle tableStyle; - + private Class clazz; /** - * column with + * Custom type conversions override the default */ - @Deprecated - private Map columnWidthMap = new HashMap(); - + private Map customConverterMap; /** - * + * Need Head */ - private Boolean autoWidth = Boolean.FALSE; - + private Boolean needHead; /** - * + * Custom type handler override the default */ - private int startRow = 0; + private List customWriteHandlerList; - private CellStyleStrategy cellStyleStrategy; + public Integer getSheetNo() { + return sheetNo; + } - private ColumnWithStyleStrategy columnWithStyleStrategy; + public void setSheetNo(Integer sheetNo) { + this.sheetNo = sheetNo; + } - public ColumnWithStyleStrategy getColumnWithStyleStrategy() { - return columnWithStyleStrategy; + public String getSheetName() { + return sheetName; } - public void setColumnWithStyleStrategy(ColumnWithStyleStrategy columnWithStyleStrategy) { - this.columnWithStyleStrategy = columnWithStyleStrategy; + public void setSheetName(String sheetName) { + this.sheetName = sheetName; } - public Sheet(int sheetNo) { - this.sheetNo = sheetNo; + public Integer getReadHeadRowNumber() { + return readHeadRowNumber; } - public Sheet(int sheetNo, int headLineMun) { - this.sheetNo = sheetNo; - this.headLineMun = headLineMun; + public void setReadHeadRowNumber(Integer readHeadRowNumber) { + this.readHeadRowNumber = readHeadRowNumber; } - public Sheet(int sheetNo, int headLineMun, Class clazz) { - this.sheetNo = sheetNo; - this.headLineMun = headLineMun; - this.clazz = clazz; + public Integer getWriteRelativeHeadRowIndex() { + return writeRelativeHeadRowIndex; } - public Sheet(int sheetNo, int headLineMun, Class clazz, String sheetName, - List> head) { - this.sheetNo = sheetNo; - this.clazz = clazz; - this.headLineMun = headLineMun; - this.sheetName = sheetName; - this.head = head; + public void setWriteRelativeHeadRowIndex(Integer writeRelativeHeadRowIndex) { + this.writeRelativeHeadRowIndex = writeRelativeHeadRowIndex; } public List> getHead() { @@ -104,93 +94,40 @@ public class Sheet { this.head = head; } - public Class getClazz() { + public Class getClazz() { return clazz; } - public void setClazz(Class clazz) { + public void setClazz(Class clazz) { this.clazz = clazz; - if (headLineMun == 0) { - this.headLineMun = 1; - } } - public int getHeadLineMun() { - return headLineMun; + public Map getCustomConverterMap() { + return customConverterMap; } - public void setHeadLineMun(int headLineMun) { - this.headLineMun = headLineMun; + public void setCustomConverterMap(Map customConverterMap) { + this.customConverterMap = customConverterMap; } - public int getSheetNo() { - return sheetNo; + public Boolean getNeedHead() { + return needHead; } - public void setSheetNo(int sheetNo) { - this.sheetNo = sheetNo; + public void setNeedHead(Boolean needHead) { + this.needHead = needHead; } - public String getSheetName() { - return sheetName; + public List getCustomWriteHandlerList() { + return customWriteHandlerList; } - public void setSheetName(String sheetName) { - this.sheetName = sheetName; - } - - public TableStyle getTableStyle() { - return tableStyle; - } - - public void setTableStyle(TableStyle tableStyle) { - this.tableStyle = tableStyle; - } - - - - public Map getColumnWidthMap() { - return columnWidthMap; - } - - public void setColumnWidthMap(Map columnWidthMap) { - this.columnWidthMap = columnWidthMap; + public void setCustomWriteHandlerList(List customWriteHandlerList) { + this.customWriteHandlerList = customWriteHandlerList; } @Override public String toString() { - return "Sheet{" + - "headLineMun=" + headLineMun + - ", sheetNo=" + sheetNo + - ", sheetName='" + sheetName + '\'' + - ", clazz=" + clazz + - ", head=" + head + - ", tableStyle=" + tableStyle + - ", columnWidthMap=" + columnWidthMap + - '}'; - } - - public Boolean getAutoWidth() { - return autoWidth; - } - - public void setAutoWidth(Boolean autoWidth) { - this.autoWidth = autoWidth; - } - - public int getStartRow() { - return startRow; - } - - public void setStartRow(int startRow) { - this.startRow = startRow; - } - - public CellStyleStrategy getCellStyleStrategy() { - return cellStyleStrategy; - } - - public void setCellStyleStrategy(CellStyleStrategy cellStyleStrategy) { - this.cellStyleStrategy = cellStyleStrategy; + return "Sheet{" + "sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' + '}'; } } diff --git a/src/main/java/com/alibaba/excel/metadata/SheetHolder.java b/src/main/java/com/alibaba/excel/metadata/SheetHolder.java deleted file mode 100644 index c51103a..0000000 --- a/src/main/java/com/alibaba/excel/metadata/SheetHolder.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.alibaba.excel.metadata; - -import java.util.Map; - -import org.apache.poi.ss.usermodel.Sheet; - -import com.alibaba.excel.write.style.CellStyleStrategy; -import com.alibaba.excel.write.style.column.ColumnWidthStyleStrategy; -import com.alibaba.excel.write.style.row.RowHighStyleStrategy; - -/** - * sheet holder - * - * @author zhuangjiaju - */ -public class SheetHolder { - /*** - * poi sheet - */ - private Sheet sheet; - /*** - * has been initialized table - */ - private Map hasBeenInitializedTable; - /** - * the header attribute of excel - */ - private ExcelHeadProperty excelHeadProperty; - - private CellStyleStrategy cellStyleStrategy; - - private ColumnWidthStyleStrategy columnWidthStyleStrategy; - private RowHighStyleStrategy rowHighStyleStrategy; - /** - * current param - */ - private com.alibaba.excel.metadata.Sheet currentSheetParam; - - private boolean needHead = true; - - public com.alibaba.excel.metadata.Sheet getCurrentSheetParam() { - return currentSheetParam; - } - - public void setCurrentSheetParam(com.alibaba.excel.metadata.Sheet currentSheetParam) { - this.currentSheetParam = currentSheetParam; - } - - public RowHighStyleStrategy getRowHighStyleStrategy() { - return rowHighStyleStrategy; - } - - public void setRowHighStyleStrategy(RowHighStyleStrategy rowHighStyleStrategy) { - this.rowHighStyleStrategy = rowHighStyleStrategy; - } - - public ColumnWidthStyleStrategy getColumnWidthStyleStrategy() { - return columnWidthStyleStrategy; - } - - public void setColumnWidthStyleStrategy(ColumnWidthStyleStrategy columnWidthStyleStrategy) { - this.columnWidthStyleStrategy = columnWidthStyleStrategy; - } - - public boolean isNeedHead() { - return needHead; - } - - public void setNeedHead(boolean needHead) { - this.needHead = needHead; - } - - public ExcelHeadProperty getExcelHeadProperty() { - return excelHeadProperty; - } - - public void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty) { - this.excelHeadProperty = excelHeadProperty; - } - - public Sheet getSheet() { - return sheet; - } - - public void setSheet(Sheet sheet) { - this.sheet = sheet; - } - - public Map getHasBeenInitializedTable() { - return hasBeenInitializedTable; - } - - public void setHasBeenInitializedTable(Map hasBeenInitializedTable) { - this.hasBeenInitializedTable = hasBeenInitializedTable; - } - - public CellStyleStrategy getCellStyleStrategy() { - return cellStyleStrategy; - } - - public void setCellStyleStrategy(CellStyleStrategy cellStyleStrategy) { - this.cellStyleStrategy = cellStyleStrategy; - } -} diff --git a/src/main/java/com/alibaba/excel/metadata/Table.java b/src/main/java/com/alibaba/excel/metadata/Table.java index afa23ff..6fb9c68 100644 --- a/src/main/java/com/alibaba/excel/metadata/Table.java +++ b/src/main/java/com/alibaba/excel/metadata/Table.java @@ -2,57 +2,89 @@ package com.alibaba.excel.metadata; import java.util.List; -import com.alibaba.excel.write.style.CellStyleStrategy; +import com.alibaba.excel.event.Handler; +import com.alibaba.excel.write.handler.WriteHandler; /** + * table + * * @author jipengfei */ public class Table { /** + * Starting from 1 */ - private Class clazz; - + private Integer tableNo; + /** + * Writes the header relative to the existing contents of the sheet. Indexes are zero-based. + */ + private Integer writeRelativeHeadRowIndex; /** + * You can only choose one of the {@link Table#head} and {@link Table#clazz} */ private List> head; - /** + * You can only choose one of the {@link Table#head} and {@link Table#clazz} */ - private int tableNo; - + private Class clazz; + /** + * Need head + */ + private Boolean needHead; /** + * Handle some extra logic. So far only for writing purposes {@link WriteHandler} + * */ - @Deprecated - private TableStyle tableStyle; + private List handler; - private CellStyleStrategy cellStyleStrategy; + public Table(Integer sheetNo) { + this(sheetNo, 0, null, null, Boolean.TRUE); + } - public CellStyleStrategy getCellStyleStrategy() { - return cellStyleStrategy; + public Table(Integer sheetNo, List> head) { + this(sheetNo, 0, head, null, Boolean.TRUE); } - public void setCellStyleStrategy(CellStyleStrategy cellStyleStrategy) { - this.cellStyleStrategy = cellStyleStrategy; + public Table(Integer sheetNo, Class clazz) { + this(sheetNo, 0, null, clazz, Boolean.TRUE); } - public TableStyle getTableStyle() { - return tableStyle; + public Table(Integer tableNo, Integer writeRelativeHeadRowIndex, List> head, Class clazz, + Boolean needHead) { + if (tableNo == null || tableNo < 1) { + throw new IllegalArgumentException("SheetNo must greater than 0"); + } + if (writeRelativeHeadRowIndex == null || writeRelativeHeadRowIndex < 0) { + throw new IllegalArgumentException("WriteRelativeHeadRowIndex must greater than -1"); + } + if (head != null && !head.isEmpty() && clazz != null) { + throw new IllegalArgumentException("Head and clazz fill in no more than one"); + } + if (needHead == null) { + throw new IllegalArgumentException("NeedHead can not be null"); + } + this.tableNo = tableNo; + this.writeRelativeHeadRowIndex = writeRelativeHeadRowIndex; + this.head = head; + this.clazz = clazz; + this.needHead = needHead; + } - public void setTableStyle(TableStyle tableStyle) { - this.tableStyle = tableStyle; + public Integer getTableNo() { + return tableNo; } - public Table(Integer tableNo) { + public void setTableNo(Integer tableNo) { this.tableNo = tableNo; } - public Class getClazz() { - return clazz; + public Integer getWriteRelativeHeadRowIndex() { + return writeRelativeHeadRowIndex; } - public void setClazz(Class clazz) { - this.clazz = clazz; + public void setWriteRelativeHeadRowIndex(Integer writeRelativeHeadRowIndex) { + this.writeRelativeHeadRowIndex = writeRelativeHeadRowIndex; } public List> getHead() { @@ -63,11 +95,32 @@ public class Table { this.head = head; } - public int getTableNo() { - return tableNo; + public Class getClazz() { + return clazz; } - public void setTableNo(int tableNo) { - this.tableNo = tableNo; + public void setClazz(Class clazz) { + this.clazz = clazz; + } + + public Boolean getNeedHead() { + return needHead; + } + + public void setNeedHead(Boolean needHead) { + this.needHead = needHead; + } + + public List getHandler() { + return handler; + } + + public void setHandler(List handler) { + this.handler = handler; + } + + @Override + public String toString() { + return "Table{" + "tableNo=" + tableNo + '}'; } } diff --git a/src/main/java/com/alibaba/excel/metadata/holder/ConfigurationSelector.java b/src/main/java/com/alibaba/excel/metadata/holder/ConfigurationSelector.java new file mode 100644 index 0000000..6ffba34 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/holder/ConfigurationSelector.java @@ -0,0 +1,43 @@ +package com.alibaba.excel.metadata.holder; + +import java.util.List; +import java.util.Map; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.write.handler.WriteHandler; + +/** + * + * Get the corresponding configuration + * + * @author zhuangjiaju + **/ +public interface ConfigurationSelector { + + /** + * What handler does the currently operated cell need to execute + * + * @return + */ + List writeHandlerList(); + + /** + * What converter does the currently operated cell need to execute + * + * @return + */ + Map converterMap(); + + /** + * Whether a header is required for the currently operated cell + * + * @return + */ + boolean needHead(); + + /** + * Writes the head relative to the existing contents of the sheet. Indexes are zero-based. + */ + int writeRelativeHeadRowIndex(); + +} diff --git a/src/main/java/com/alibaba/excel/metadata/holder/SheetHolder.java b/src/main/java/com/alibaba/excel/metadata/holder/SheetHolder.java new file mode 100644 index 0000000..3136bad --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/holder/SheetHolder.java @@ -0,0 +1,131 @@ +package com.alibaba.excel.metadata.holder; + +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Sheet; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.metadata.ExcelHeadProperty; +import com.alibaba.excel.write.handler.WriteHandler; + +/** + * sheet holder + * + * @author zhuangjiaju + */ +public class SheetHolder implements ConfigurationSelector { + /*** + * poi sheet + */ + private Sheet sheet; + + /*** + * has been initialized table + */ + private Map hasBeenInitializedTable; + /** + * Need Head + */ + private Boolean needHead; + /** + * Write handler for workbook + */ + private List writeHandlerList; + /** + * Converter for workbook + */ + private Map converterMap; + /** + * current param + */ + private com.alibaba.excel.metadata.Sheet sheetParam; + + /** + * Excel head property + */ + private ExcelHeadProperty excelHeadProperty; + /** + * Writes the head relative to the existing contents of the sheet. Indexes are zero-based. + */ + private Integer writeRelativeHeadRowIndex; + + public Sheet getSheet() { + return sheet; + } + + public void setSheet(Sheet sheet) { + this.sheet = sheet; + } + + public Map getHasBeenInitializedTable() { + return hasBeenInitializedTable; + } + + public void setHasBeenInitializedTable(Map hasBeenInitializedTable) { + this.hasBeenInitializedTable = hasBeenInitializedTable; + } + + public Boolean getNeedHead() { + return needHead; + } + + public void setNeedHead(Boolean needHead) { + this.needHead = needHead; + } + + public List getWriteHandlerList() { + return writeHandlerList; + } + + public void setWriteHandlerList(List writeHandlerList) { + this.writeHandlerList = writeHandlerList; + } + + public Map getConverterMap() { + return converterMap; + } + + public void setConverterMap(Map converterMap) { + this.converterMap = converterMap; + } + + public com.alibaba.excel.metadata.Sheet getSheetParam() { + return sheetParam; + } + + public void setSheetParam(com.alibaba.excel.metadata.Sheet sheetParam) { + this.sheetParam = sheetParam; + } + + public ExcelHeadProperty getExcelHeadProperty() { + return excelHeadProperty; + } + + public void setExcelHeadProperty(ExcelHeadProperty excelHeadProperty) { + this.excelHeadProperty = excelHeadProperty; + } + + public Integer getWriteRelativeHeadRowIndex() { + return writeRelativeHeadRowIndex; + } + + public void setWriteRelativeHeadRowIndex(Integer writeRelativeHeadRowIndex) { + this.writeRelativeHeadRowIndex = writeRelativeHeadRowIndex; + } + + @Override + public List writeHandlerList() { + return getWriteHandlerList(); + } + + @Override + public Map converterMap() { + return getConverterMap(); + } + + @Override + public boolean needHead() { + return getNeedHead(); + } +} diff --git a/src/main/java/com/alibaba/excel/metadata/TableHolder.java b/src/main/java/com/alibaba/excel/metadata/holder/TableHolder.java similarity index 91% rename from src/main/java/com/alibaba/excel/metadata/TableHolder.java rename to src/main/java/com/alibaba/excel/metadata/holder/TableHolder.java index d07c3b6..dfff6ed 100644 --- a/src/main/java/com/alibaba/excel/metadata/TableHolder.java +++ b/src/main/java/com/alibaba/excel/metadata/holder/TableHolder.java @@ -1,5 +1,7 @@ -package com.alibaba.excel.metadata; +package com.alibaba.excel.metadata.holder; +import com.alibaba.excel.metadata.ExcelHeadProperty; +import com.alibaba.excel.metadata.Table; import com.alibaba.excel.write.style.CellStyleStrategy; import com.alibaba.excel.write.style.column.ColumnWidthStyleStrategy; import com.alibaba.excel.write.style.row.RowHighStyleStrategy; @@ -9,7 +11,7 @@ import com.alibaba.excel.write.style.row.RowHighStyleStrategy; * * @author zhuangjiaju */ -public class TableHolder { +public class TableHolder implements ConfigurationSelector{ /*** * poi sheet */ diff --git a/src/main/java/com/alibaba/excel/metadata/holder/WorkbookHolder.java b/src/main/java/com/alibaba/excel/metadata/holder/WorkbookHolder.java new file mode 100644 index 0000000..209db63 --- /dev/null +++ b/src/main/java/com/alibaba/excel/metadata/holder/WorkbookHolder.java @@ -0,0 +1,92 @@ +package com.alibaba.excel.metadata.holder; + +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Workbook; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.write.handler.WriteHandler; + +/** + * Workbook holder + * + * @author zhuangjiaju + */ +public class WorkbookHolder implements ConfigurationSelector { + /*** + * poi Workbook + */ + private Workbook workbook; + /** + * Need Head + */ + private Boolean needHead; + /** + * Write handler for workbook + */ + private List writeHandlerList; + /** + * Converter for workbook + */ + private Map converterMap; + /** + * prevent duplicate creation of sheet objects + */ + private Map hasBeenInitializedSheet; + + public Workbook getWorkbook() { + return workbook; + } + + public void setWorkbook(Workbook workbook) { + this.workbook = workbook; + } + + public Boolean getNeedHead() { + return needHead; + } + + public void setNeedHead(Boolean needHead) { + this.needHead = needHead; + } + + public List getWriteHandlerList() { + return writeHandlerList; + } + + public void setWriteHandlerList(List writeHandlerList) { + this.writeHandlerList = writeHandlerList; + } + + public Map getConverterMap() { + return converterMap; + } + + public void setConverterMap(Map converterMap) { + this.converterMap = converterMap; + } + + public Map getHasBeenInitializedSheet() { + return hasBeenInitializedSheet; + } + + public void setHasBeenInitializedSheet(Map hasBeenInitializedSheet) { + this.hasBeenInitializedSheet = hasBeenInitializedSheet; + } + + @Override + public List writeHandlerList() { + return getWriteHandlerList(); + } + + @Override + public Map converterMap() { + return getConverterMap(); + } + + @Override + public boolean needHead() { + return getNeedHead(); + } +} diff --git a/src/main/java/com/alibaba/excel/util/BooleanUtils.java b/src/main/java/com/alibaba/excel/util/BooleanUtils.java new file mode 100644 index 0000000..a216042 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/BooleanUtils.java @@ -0,0 +1,29 @@ +package com.alibaba.excel.util; + +/** + * boolean util + * + * @author zhuangjiaju + */ +public class BooleanUtils { + + private static final String TRUE_NUMBER = "1"; + private static final String FALSE_NUMBER = "0"; + + /** + * String to boolean + * + *
  • + * + * @param str + * @return + */ + public static Boolean valueOf(String str) { + if (TRUE_NUMBER.equals(str)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +} diff --git a/src/main/java/com/alibaba/excel/util/DateUtils.java b/src/main/java/com/alibaba/excel/util/DateUtils.java new file mode 100644 index 0000000..08310f9 --- /dev/null +++ b/src/main/java/com/alibaba/excel/util/DateUtils.java @@ -0,0 +1,101 @@ +package com.alibaba.excel.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.alibaba.excel.exception.ExcelDataConvertException; + +/** + * Date utils + * + * @author zhuangjiaju + **/ +public class DateUtils { + public static final String DATE_FORMAT_14 = "yyyyMMddHHmmss"; + public static final String DATE_FORMAT_17 = "yyyyMMdd HH:mm:ss"; + public static final String DATE_FORMAT_19 = "yyyy-MM-dd HH:mm:ss"; + public static final String DATE_FORMAT_19_FORWARD_SLASH = "yyyy/MM/dd HH:mm:ss"; + private static final String MINUS = "-"; + + private DateUtils() {} + + /** + * convert string to date + * + * @param dateString + * @param dateFormat + * @return + * @throws ParseException + */ + public static Date parseDate(String dateString, String dateFormat) throws ParseException { + if (StringUtils.isEmpty(dateFormat)) { + dateFormat = switchDateFormat(dateString); + } + return new SimpleDateFormat(dateFormat).parse(dateString); + } + + /** + * convert string to date + * + * @param dateString + * @return + * @throws ParseException + */ + public static Date parseDate(String dateString) throws ParseException { + return parseDate(switchDateFormat(dateString), null); + } + + /** + * switch date format + * + * @param dateString + * @return + */ + private static String switchDateFormat(String dateString) { + int length = dateString.length(); + switch (length) { + case 19: + if (dateString.contains(MINUS)) { + return DATE_FORMAT_19; + } else { + return DATE_FORMAT_19_FORWARD_SLASH; + } + case 17: + return DATE_FORMAT_17; + case 14: + return DATE_FORMAT_14; + default: + throw new ExcelDataConvertException("can not find date format for:" + dateString); + } + } + + /** + * Format date + *

    + * yyyy-MM-dd HH:mm:ss + * + * @param date + * @return + */ + public static String format(Date date) { + return format(date, null); + } + + /** + * Format date + * + * @param date + * @param dateFormat + * @return + */ + public static String format(Date date, String dateFormat) { + if (date == null) { + return ""; + } + if (StringUtils.isEmpty(dateFormat)) { + dateFormat = DATE_FORMAT_19; + } + return new SimpleDateFormat(dateFormat).format(date); + } +} diff --git a/src/main/java/com/alibaba/excel/util/StyleUtil.java b/src/main/java/com/alibaba/excel/util/StyleUtil.java index 7e83c88..c4faa12 100644 --- a/src/main/java/com/alibaba/excel/util/StyleUtil.java +++ b/src/main/java/com/alibaba/excel/util/StyleUtil.java @@ -1,14 +1,11 @@ package com.alibaba.excel.util; -import java.util.Map; - import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.Workbook; @@ -17,22 +14,6 @@ import org.apache.poi.ss.usermodel.Workbook; */ public class StyleUtil { - public static void defaultCellStyle(Workbook workbook, CellStyle newCellStyle) { - Font font = workbook.createFont(); - font.setFontName("宋体"); - font.setFontHeightInPoints((short)14); - font.setBold(true); - newCellStyle.setFont(font); - newCellStyle.setWrapText(true); - newCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); - newCellStyle.setAlignment(HorizontalAlignment.CENTER); - newCellStyle.setLocked(true); - newCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); - newCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); - newCellStyle.setBorderBottom(BorderStyle.THIN); - newCellStyle.setBorderLeft(BorderStyle.THIN); - } - /** * * @param workbook @@ -63,9 +44,34 @@ public class StyleUtil { * @param indexedColors * @return */ - public static CellStyle buildCellStyle(Workbook workbook, com.alibaba.excel.metadata.Font f, + public static CellStyle buildHeadCellStyle(Workbook workbook, com.alibaba.excel.metadata.Font f, + IndexedColors indexedColors) { + CellStyle cellStyle = workbook.createCellStyle(); + return buildCellStyle(workbook, cellStyle, f, indexedColors); + } + + /** + * + * @param workbook + * @param f + * @param indexedColors + * @return + */ + public static CellStyle buildContentCellStyle(Workbook workbook, com.alibaba.excel.metadata.Font f, IndexedColors indexedColors) { CellStyle cellStyle = buildDefaultCellStyle(workbook); + return buildCellStyle(workbook, cellStyle, f, indexedColors); + } + + /** + * + * @param workbook + * @param f + * @param indexedColors + * @return + */ + private static CellStyle buildCellStyle(Workbook workbook, CellStyle cellStyle, com.alibaba.excel.metadata.Font f, + IndexedColors indexedColors) { if (f != null) { Font font = workbook.createFont(); font.setFontName(f.getFontName()); @@ -78,24 +84,4 @@ public class StyleUtil { } return cellStyle; } - - /** - * Convert {@link com.alibaba.excel.metadata.CellStyle} to {@link CellStyle} - * - * @param workbook - * @param cellStyle - * @return - */ - public static CellStyle buildCellStyle(Workbook workbook, com.alibaba.excel.metadata.CellStyle cellStyle) { - return buildCellStyle(workbook, cellStyle.getSimpleFont(), cellStyle.getIndexedColors()); - } - - public static Sheet buildSheetStyle(Sheet currentSheet, Map sheetWidthMap) { - currentSheet.setDefaultColumnWidth(20); - for (Map.Entry entry : sheetWidthMap.entrySet()) { - currentSheet.setColumnWidth(entry.getKey(), entry.getValue()); - } - return currentSheet; - } - } diff --git a/src/main/java/com/alibaba/excel/util/TypeUtil.java b/src/main/java/com/alibaba/excel/util/TypeUtil.java deleted file mode 100644 index 185b331..0000000 --- a/src/main/java/com/alibaba/excel/util/TypeUtil.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.alibaba.excel.util; - -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.text.ParseException; -import java.text.SimpleDateFormat; -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 - */ -public class TypeUtil { - - private static List DATE_FORMAT_LIST = new ArrayList(4); - - static { - DATE_FORMAT_LIST.add("yyyy/MM/dd HH:mm:ss"); - DATE_FORMAT_LIST.add("yyyy-MM-dd HH:mm:ss"); - DATE_FORMAT_LIST.add("yyyyMMdd HH:mm:ss"); - } - - public static Boolean isNum(Field field) { - if (field == null) { - return false; - } - if (Integer.class.equals(field.getType()) || int.class.equals(field.getType())) { - return true; - } - if (Double.class.equals(field.getType()) || double.class.equals(field.getType())) { - return true; - } - - if (Long.class.equals(field.getType()) || long.class.equals(field.getType())) { - return true; - } - - if (BigDecimal.class.equals(field.getType())) { - return true; - } - return false; - } - - 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) { - return true; - } - return false; - } - - public static String getDefaultDateString(Date date) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - return simpleDateFormat.format(date); - - } - - public static Date getSimpleDateFormatDate(String value, String format) { - if (!StringUtils.isEmpty(value)) { - Date date = null; - if (!StringUtils.isEmpty(format)) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); - try { - date = simpleDateFormat.parse(value); - return date; - } catch (ParseException e) { - } - } - for (String dateFormat : DATE_FORMAT_LIST) { - try { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); - date = simpleDateFormat.parse(value); - } catch (ParseException e) { - } - if (date != null) { - break; - } - } - - return date; - - } - return null; - - } - - - public static String formatFloat(String value) { - if (null != value && value.contains(".")) { - if (isNumeric(value)) { - try { - BigDecimal decimal = new BigDecimal(value); - BigDecimal setScale = decimal.setScale(10, RoundingMode.HALF_DOWN).stripTrailingZeros(); - return setScale.toPlainString(); - } catch (Exception e) { - } - } - } - return value; - } - - public static String formatFloat0(String value, int n) { - if (null != value && value.contains(".")) { - if (isNumeric(value)) { - try { - BigDecimal decimal = new BigDecimal(value); - BigDecimal setScale = decimal.setScale(n, RoundingMode.HALF_DOWN); - return setScale.toPlainString(); - } catch (Exception e) { - } - } - } - return value; - } - - public static final Pattern pattern = Pattern.compile("[\\+\\-]?[\\d]+([\\.][\\d]*)?([Ee][+-]?[\\d]+)?$"); - - private static boolean isNumeric(String str) { - Matcher isNum = pattern.matcher(str); - if (!isNum.matches()) { - return false; - } - return true; - } - - public static String formatDate(Date cellValue, String format) { - SimpleDateFormat simpleDateFormat; - if (!StringUtils.isEmpty(format)) { - simpleDateFormat = new SimpleDateFormat(format); - } else { - simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - } - return simpleDateFormat.format(cellValue); - } -} diff --git a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java index ed9716a..e97a4ff 100644 --- a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java +++ b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java @@ -30,22 +30,6 @@ public class WorkBookUtil { return workbook; } - public static Sheet createOrGetSheet(Workbook workbook, com.alibaba.excel.metadata.Sheet sheet) { - Sheet sheet1 = null; - try { - try { - sheet1 = workbook.getSheetAt(sheet.getSheetNo()-1); - } catch (Exception e) { - } - if (null == sheet1) { - sheet1 = createSheet(workbook, sheet); - buildSheetStyle(sheet1,sheet.getColumnWidthMap()); - } - } catch (Exception e) { - throw new RuntimeException("constructCurrentSheet error", e); - } - return sheet1; - } public static Sheet createSheet(Workbook workbook, com.alibaba.excel.metadata.Sheet sheet) { return workbook.createSheet(sheet.getSheetName() != null ? sheet.getSheetName() : sheet.getSheetNo() + ""); diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java index 4135f31..ddb20c3 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java @@ -1,24 +1,15 @@ package com.alibaba.excel.write; +import java.util.List; + import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; -import com.alibaba.excel.write.merge.MergeStrategy; - -import java.util.List; /** * @author jipengfei */ public interface ExcelBuilder { - /** - * workBook increase value - * - * @param data java basic type or java model extend BaseModel - * @param startRow Start row number - */ - void addContent(List data, int startRow); - /** * WorkBook increase value * @@ -39,9 +30,13 @@ public interface ExcelBuilder { /** * Creates new cell range. Indexes are zero-based. * - * @param strategies the merge strategy + * @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} */ - void merge(List strategies); + @Deprecated + void merge(int firstRow, int lastRow, int firstCol, int lastCol); /** * Close io diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index da09a90..a520732 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -1,10 +1,9 @@ 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 java.util.Map; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -14,10 +13,8 @@ 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; +import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.ExcelColumnProperty; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; @@ -25,37 +22,26 @@ import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.util.CollectionUtils; import com.alibaba.excel.util.POITempFile; import com.alibaba.excel.util.WorkBookUtil; -import com.alibaba.excel.write.merge.MergeStrategy; +import com.alibaba.excel.write.handler.WriteHandler; import net.sf.cglib.beans.BeanMap; /** * @author jipengfei */ -public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter { - +public class ExcelBuilderImpl implements ExcelBuilder { private WriteContext context; - private final List converters = new ArrayList(); - - public ExcelBuilderImpl(InputStream templateInputStream, - OutputStream out, - ExcelTypeEnum excelType, - boolean needHead, WriteHandler writeHandler, List converters) { - try { - //初始化时候创建临时缓存目录,用于规避POI在并发写bug - POITempFile.createPOIFilesDirectory(); - if (converters != null) { - converters.addAll(converters); - } - context = new WriteContextImpl(templateInputStream, out, excelType, needHead, writeHandler, this); - } catch (Exception e) { - throw new RuntimeException(e); - } + + public ExcelBuilderImpl(InputStream templateInputStream, OutputStream out, ExcelTypeEnum excelType, + boolean needHead, Map customConverterMap, List customWriteHandlerList) { + // 初始化时候创建临时缓存目录,用于规避POI在并发写bug + POITempFile.createPOIFilesDirectory(); + context = new WriteContextImpl(templateInputStream, out, excelType, needHead, customConverterMap, + customWriteHandlerList); } - @Override - public void addContent(List data, int startRow) { + private void doAddContent(List data, int startRow) { if (CollectionUtils.isEmpty(data)) { return; } @@ -80,35 +66,25 @@ public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter { @Override public void addContent(List data, Sheet sheetParam) { context.currentSheet(sheetParam); - addContent(data, sheetParam.getStartRow()); + doAddContent(data, sheetParam.getWriteRelativeHeadRowIndex()); } @Override public void addContent(List data, Sheet sheetParam, Table table) { context.currentSheet(sheetParam); context.currentTable(table); - addContent(data, sheetParam.getStartRow()); + doAddContent(data, sheetParam.getWriteRelativeHeadRowIndex()); } - @Override - public void merge(List strategies) { - if (strategies != null) { - for (MergeStrategy ms : strategies) { - CellRangeAddress cra = new CellRangeAddress(ms.getFirstRow(), ms.getLastRow(), ms.getFirstCol(), ms.getLastCol()); - context.getCurrentSheet().addMergedRegion(cra); - } - } + public void finish() { + context.finish(); } @Override - public void finish() { - try { - context.getWorkbook().write(context.getOutputStream()); - context.getWorkbook().close(); - } catch (IOException e) { - throw new ExcelGenerateException("IO error", e); - } + public void merge(int firstRow, int lastRow, int firstCol, int lastCol) { + CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol); + context.getCurrentSheet().addMergedRegion(cra); } private void addBasicTypeToExcel(List oneRowData, Row row) { @@ -130,11 +106,13 @@ public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter { BeanMap beanMap = BeanMap.create(oneRowData); for (ExcelColumnProperty excelHeadProperty : context.getExcelHeadProperty().getColumnPropertyList()) { BaseRowModel baseRowModel = (BaseRowModel)oneRowData; - CellStyle cellStyle = baseRowModel.getStyle(i) != null ? baseRowModel.getStyle(i) - : context.getCurrentContentStyle(); + CellStyle cellStyle = + baseRowModel.getStyle(i) != null ? baseRowModel.getStyle(i) : context.getCurrentContentStyle(); Object value = beanMap.get(excelHeadProperty.getField().getName()); + // excelHeadProperty.getField().getType(); + Cell cell = WorkBookUtil.createCell(row, i, cellStyle); - cell = convertValue(cell, value, excelHeadProperty); + cell.setCL cell = convertValue(cell, value, excelHeadProperty); if (null != context.getWriteHandler()) { context.getWriteHandler().cell(i, cell); } @@ -145,6 +123,8 @@ public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter { private Cell convertValue(Cell cell, Object value, ExcelColumnProperty excelHeadProperty) { if (!CollectionUtils.isEmpty(this.converters)) { for (Converter c : this.converters) { + CellData c.convertToExcelData(excelHeadProperty); + if (value != null && c.support(value)) { return c.convert(cell, value, excelHeadProperty); } @@ -165,13 +145,4 @@ public class ExcelBuilderImpl implements ExcelBuilder, ConverterRegistryCenter { } } - @Override - public void register(Converter converter) { - this.converters.add(converter); - } - - @Override - public List getConverters() { - return this.converters; - } } diff --git a/src/main/java/com/alibaba/excel/write/ExcelWriterBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelWriterBuilder.java deleted file mode 100644 index 869b787..0000000 --- a/src/main/java/com/alibaba/excel/write/ExcelWriterBuilder.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.alibaba.excel.write; - -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.excel.ExcelWriter; -import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.support.ExcelTypeEnum; - -public class ExcelWriterBuilder { - /** - * Excel type - */ - private ExcelTypeEnum excelType; - - /** - * Final output stream - */ - private OutputStream outputStream; - - /** - * - */ - private List customConverter = new ArrayList(); - - public ExcelWriter build() { - new ExcelBuilderImpl(templateInputStream, outputStream, typeEnum, needHead, writeHandler, converters); - } -} diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java new file mode 100644 index 0000000..20ecc32 --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterBuilder.java @@ -0,0 +1,120 @@ +package com.alibaba.excel.write.builder; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.write.handler.WriteHandler; + +/** + * Build ExcelBuilder + * + * @author zhuangjiaju + */ +public class ExcelWriterBuilder { + /** + * Excel type + */ + private ExcelTypeEnum excelType; + /** + * Final output stream + */ + private OutputStream outputStream; + /** + * Template input stream + */ + private InputStream templateInputStream; + /** + * Custom type conversions override the default + */ + private Map customConverterMap = new HashMap(); + /** + * Need Head + */ + private Boolean needHead; + /** + * Custom type handler override the default + */ + private List customWriteHandlerList = new ArrayList(); + + public ExcelWriterBuilder excelType(ExcelTypeEnum excelType) { + this.excelType = excelType; + return this; + } + + public ExcelWriterBuilder outputFile(OutputStream outputStream) { + this.outputStream = outputStream; + return this; + } + + public ExcelWriterBuilder outputFile(File outputFile) throws FileNotFoundException { + return outputFile(new FileOutputStream(outputFile)); + } + + public ExcelWriterBuilder outputFile(String outputPathName) throws FileNotFoundException { + return outputFile(new File(outputPathName)); + } + + public ExcelWriterBuilder outputFile(URI outputUri) throws FileNotFoundException { + return outputFile(new File(outputUri)); + } + + public ExcelWriterBuilder withTemplate(InputStream templateInputStream) { + this.templateInputStream = templateInputStream; + return this; + } + + public ExcelWriterBuilder withTemplate(File templateFile) throws FileNotFoundException { + return withTemplate(new FileInputStream(templateFile)); + } + + public ExcelWriterBuilder withTemplate(String templatePathName) throws FileNotFoundException { + return withTemplate(new File(templatePathName)); + } + + public ExcelWriterBuilder withTemplate(URI templateUri) throws FileNotFoundException { + return withTemplate(new File(templateUri)); + } + + /** + * Custom type conversions override the default. + * + * @param converter + * @return + */ + public ExcelWriterBuilder registerConverter(Converter converter) { + this.customConverterMap.put(converter.supportJavaTypeKey(), converter); + return this; + } + + /** + * Default required header + * + * @return + */ + public ExcelWriterBuilder doNotNeedHead() { + this.needHead = Boolean.FALSE; + return this; + } + + public ExcelWriterBuilder registerWriteHandler(WriteHandler excelWriteHandler) { + this.customWriteHandlerList.add(excelWriteHandler); + return this; + } + + public ExcelWriter build() { + return new ExcelWriter(templateInputStream, outputStream, excelType, needHead, customConverterMap, + customWriteHandlerList); + } +} diff --git a/src/main/java/com/alibaba/excel/write/handler/CellExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java similarity index 82% rename from src/main/java/com/alibaba/excel/write/handler/CellExcelWriteHandler.java rename to src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java index ed78b98..e02e760 100644 --- a/src/main/java/com/alibaba/excel/write/handler/CellExcelWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/CellWriteHandler.java @@ -4,8 +4,8 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.metadata.SheetHolder; -import com.alibaba.excel.metadata.TableHolder; +import com.alibaba.excel.metadata.holder.SheetHolder; +import com.alibaba.excel.metadata.holder.TableHolder; import com.sun.istack.internal.Nullable; /** @@ -13,7 +13,7 @@ import com.sun.istack.internal.Nullable; * * @author zhuangjiaju */ -public interface CellExcelWriteHandler extends ExcelWriteHandler { +public interface CellWriteHandler extends WriteHandler { /** * called before create the cell diff --git a/src/main/java/com/alibaba/excel/write/handler/RowExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java similarity index 80% rename from src/main/java/com/alibaba/excel/write/handler/RowExcelWriteHandler.java rename to src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java index d0c4099..db7ed3d 100644 --- a/src/main/java/com/alibaba/excel/write/handler/RowExcelWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java @@ -2,8 +2,8 @@ package com.alibaba.excel.write.handler; import org.apache.poi.ss.usermodel.Row; -import com.alibaba.excel.metadata.SheetHolder; -import com.alibaba.excel.metadata.TableHolder; +import com.alibaba.excel.metadata.holder.SheetHolder; +import com.alibaba.excel.metadata.holder.TableHolder; import com.sun.istack.internal.Nullable; /** @@ -11,7 +11,7 @@ import com.sun.istack.internal.Nullable; * * @author zhuangjiaju */ -public interface RowExcelWriteHandler extends ExcelWriteHandler { +public interface RowWriteHandler extends WriteHandler { /** * called before create the row diff --git a/src/main/java/com/alibaba/excel/write/handler/SheetExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java similarity index 80% rename from src/main/java/com/alibaba/excel/write/handler/SheetExcelWriteHandler.java rename to src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java index d46eaab..02a98a2 100644 --- a/src/main/java/com/alibaba/excel/write/handler/SheetExcelWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/SheetWriteHandler.java @@ -2,14 +2,14 @@ package com.alibaba.excel.write.handler; import org.apache.poi.ss.usermodel.Workbook; -import com.alibaba.excel.metadata.SheetHolder; +import com.alibaba.excel.metadata.holder.SheetHolder; /** * intercepts handle sheet creation * * @author zhuangjiaju */ -public interface SheetExcelWriteHandler extends ExcelWriteHandler { +public interface SheetWriteHandler extends WriteHandler { /** * called before create the sheet diff --git a/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java new file mode 100644 index 0000000..9d1e5cc --- /dev/null +++ b/src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java @@ -0,0 +1,25 @@ +package com.alibaba.excel.write.handler; + +import org.apache.poi.ss.usermodel.Workbook; + +/** + * intercepts handle Workbook creation + * + * @author zhuangjiaju + */ +public interface WorkbookWriteHandler extends WriteHandler { + + /** + * called before create the sheet + * + * @param writeContext + */ + void beforeWorkbookCreate(); + + /** + * called after the sheet is created + * + * @param writeContext + */ + void afterWorkbookCreate(Workbook workbook); +} diff --git a/src/main/java/com/alibaba/excel/write/handler/ExcelWriteHandler.java b/src/main/java/com/alibaba/excel/write/handler/WriteHandler.java similarity index 73% rename from src/main/java/com/alibaba/excel/write/handler/ExcelWriteHandler.java rename to src/main/java/com/alibaba/excel/write/handler/WriteHandler.java index d37fc02..f89a624 100644 --- a/src/main/java/com/alibaba/excel/write/handler/ExcelWriteHandler.java +++ b/src/main/java/com/alibaba/excel/write/handler/WriteHandler.java @@ -7,4 +7,4 @@ import com.alibaba.excel.event.Handler; * * @author zhuangjiaju */ -public interface ExcelWriteHandler extends Handler {} +public interface WriteHandler extends Handler {} diff --git a/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java index 35e84e3..3a93698 100644 --- a/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java +++ b/src/main/java/com/alibaba/excel/write/merge/AbstractMergeStrategy.java @@ -5,11 +5,11 @@ import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.metadata.SheetHolder; -import com.alibaba.excel.metadata.TableHolder; -import com.alibaba.excel.write.handler.CellExcelWriteHandler; +import com.alibaba.excel.metadata.holder.SheetHolder; +import com.alibaba.excel.metadata.holder.TableHolder; +import com.alibaba.excel.write.handler.CellWriteHandler; -public abstract class AbstractMergeStrategy implements CellExcelWriteHandler { +public abstract class AbstractMergeStrategy implements CellWriteHandler { @Override public void beforeCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Row row, Head head, diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java index a96e834..56f7b7a 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java @@ -4,18 +4,25 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Workbook; +import com.alibaba.excel.event.NotRepeatExecutor; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.metadata.SheetHolder; -import com.alibaba.excel.metadata.TableHolder; -import com.alibaba.excel.write.handler.CellExcelWriteHandler; -import com.alibaba.excel.write.handler.WookbookExcelWriteHandler; +import com.alibaba.excel.metadata.holder.SheetHolder; +import com.alibaba.excel.metadata.holder.TableHolder; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.WorkbookWriteHandler; -public abstract class AbstractCellStyleStrategy implements CellExcelWriteHandler, WookbookExcelWriteHandler { +public abstract class AbstractCellStyleStrategy + implements CellWriteHandler, WorkbookWriteHandler, NotRepeatExecutor { @Override - public void beforeWookbookCreate() {} + public String uniqueValue() { + return "CellStyleStrategy"; + } + + @Override + public void beforeWorkbookCreate() {} @Override - public void afterWookbookCreate(Workbook workbook) { + public void afterWorkbookCreate(Workbook workbook) { initCellStyle(workbook); } diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractColumnCellStyleStrategy.java similarity index 92% rename from src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java rename to src/main/java/com/alibaba/excel/write/style/AbstractColumnCellStyleStrategy.java index 4fcd180..a257e43 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractVerticalCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/AbstractColumnCellStyleStrategy.java @@ -11,9 +11,12 @@ import com.alibaba.excel.metadata.Head; import com.alibaba.excel.util.StyleUtil; /** - * Head of style shareholders and content of style loop + * + * Use the same style for the column + * + * @author zhuangjiaju */ -public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyleStrategy { +public abstract class AbstractColumnCellStyleStrategy extends AbstractCellStyleStrategy { private Workbook workbook; private Map headCellStyleCache = new HashMap(); @@ -47,7 +50,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl } /** - * Returns the column width corresponding to each column header + * Returns the column width corresponding to each column head * * @param head * @return @@ -55,7 +58,7 @@ public abstract class AbstractVerticalCellStyleStrategy extends AbstractCellStyl protected abstract com.alibaba.excel.metadata.CellStyle headCellStyle(Head head); /** - * Returns the column width corresponding to each column header + * Returns the column width corresponding to each column head * * @param head * @return diff --git a/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/RowCellStyleStrategy.java similarity index 57% rename from src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java rename to src/main/java/com/alibaba/excel/write/style/RowCellStyleStrategy.java index aecc7c6..4778a1b 100644 --- a/src/main/java/com/alibaba/excel/write/style/HorizontalCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/RowCellStyleStrategy.java @@ -10,7 +10,13 @@ import com.alibaba.excel.metadata.CellStyle; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.util.StyleUtil; -public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { +/** + * + * Use the same style for the row + * + * @author zhuangjiaju + */ +public class RowCellStyleStrategy extends AbstractCellStyleStrategy { private CellStyle headCellStyle; private List contentCellStyleList; @@ -18,18 +24,12 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { private org.apache.poi.ss.usermodel.CellStyle poiHeadCellStyle; private List poiContentCellStyleList; - public HorizontalCellStyleStrategy(CellStyle headCellStyle, List contentCellStyleList) { - if (headCellStyle == null || contentCellStyleList == null || contentCellStyleList.isEmpty()) { - throw new IllegalArgumentException("All parameters can not be null"); - } + public RowCellStyleStrategy(CellStyle headCellStyle, List contentCellStyleList) { this.headCellStyle = headCellStyle; this.contentCellStyleList = contentCellStyleList; } - public HorizontalCellStyleStrategy(CellStyle headCellStyle, CellStyle contentCellStyle) { - if (headCellStyle == null || contentCellStyle == null) { - throw new IllegalArgumentException("All parameters can not be null"); - } + public RowCellStyleStrategy(CellStyle headCellStyle, CellStyle contentCellStyle) { this.headCellStyle = headCellStyle; contentCellStyleList = new ArrayList(); contentCellStyleList.add(contentCellStyle); @@ -37,20 +37,30 @@ public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { @Override protected void initCellStyle(Workbook workbook) { - poiHeadCellStyle = StyleUtil.buildCellStyle(workbook, headCellStyle); - poiContentCellStyleList = new ArrayList(); - for (CellStyle cellStyle : contentCellStyleList) { - poiContentCellStyleList.add(StyleUtil.buildCellStyle(workbook, cellStyle)); + if (headCellStyle != null) { + poiHeadCellStyle = StyleUtil.buildCellStyle(workbook, headCellStyle); + } + if (contentCellStyleList != null && !contentCellStyleList.isEmpty()) { + poiContentCellStyleList = new ArrayList(); + for (CellStyle cellStyle : contentCellStyleList) { + poiContentCellStyleList.add(StyleUtil.buildCellStyle(workbook, cellStyle)); + } } } @Override protected void setHeadCellStyle(Cell cell, Head head, int relativeRowIndex) { + if (poiHeadCellStyle == null) { + return; + } cell.setCellStyle(poiHeadCellStyle); } @Override protected void setContentCellStyle(Cell cell, Head head, int relativeRowIndex) { + if (poiContentCellStyleList == null || poiContentCellStyleList.isEmpty()) { + return; + } cell.setCellStyle(poiContentCellStyleList.get(relativeRowIndex % poiContentCellStyleList.size())); } diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java index ce78053..0f46980 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractColumnWidthStyleStrategy.java @@ -4,17 +4,23 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; +import com.alibaba.excel.event.NotRepeatExecutor; import com.alibaba.excel.metadata.Head; -import com.alibaba.excel.metadata.SheetHolder; -import com.alibaba.excel.metadata.TableHolder; -import com.alibaba.excel.write.handler.CellExcelWriteHandler; +import com.alibaba.excel.metadata.holder.SheetHolder; +import com.alibaba.excel.metadata.holder.TableHolder; +import com.alibaba.excel.write.handler.CellWriteHandler; /** * Column width style strategy * * @author zhuangjiaju */ -public abstract class AbstractColumnWidthStyleStrategy implements CellExcelWriteHandler { +public abstract class AbstractColumnWidthStyleStrategy implements CellWriteHandler, NotRepeatExecutor { + + @Override + public String uniqueValue() { + return "ColumnWidthStyleStrategy"; + } @Override public void beforeCellCreate(SheetHolder sheetHolder, TableHolder tableHolder, Row row, Head head, diff --git a/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java index f58b92e..aec327b 100644 --- a/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/column/AbstractHeadColumnWidthStyleStrategy.java @@ -17,7 +17,7 @@ public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColum } /** - * Returns the column width corresponding to each column header + * Returns the column width corresponding to each column head * * @param head * @return diff --git a/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHighStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHighStyleStrategy.java index 9ccc332..aeb4c68 100644 --- a/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHighStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/row/AbstractRowHighStyleStrategy.java @@ -2,11 +2,17 @@ package com.alibaba.excel.write.style.row; import org.apache.poi.ss.usermodel.Row; -import com.alibaba.excel.metadata.SheetHolder; -import com.alibaba.excel.metadata.TableHolder; -import com.alibaba.excel.write.handler.RowExcelWriteHandler; +import com.alibaba.excel.event.NotRepeatExecutor; +import com.alibaba.excel.metadata.holder.SheetHolder; +import com.alibaba.excel.metadata.holder.TableHolder; +import com.alibaba.excel.write.handler.RowWriteHandler; -public abstract class AbstractRowHighStyleStrategy implements RowExcelWriteHandler { +public abstract class AbstractRowHighStyleStrategy implements RowWriteHandler, NotRepeatExecutor { + + @Override + public String uniqueValue() { + return "RowHighStyleStrategy"; + } @Override public void beforeRowCreate(SheetHolder sheetHolder, TableHolder tableHolder, int rowIndex, int relativeRowIndex, diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml new file mode 100644 index 0000000..1814024 --- /dev/null +++ b/src/test/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + ${LOG_PATTERN} + + + INFO + + + + + +