());
+ xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());
}
}
diff --git a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
index 5c778a84..e2b169e3 100644
--- a/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
+++ b/src/main/java/com/alibaba/excel/annotation/ExcelProperty.java
@@ -23,7 +23,7 @@ public @interface ExcelProperty {
*
* write: It automatically merges when you have more than one head
*
- * read: When you have multiple heads, take the first one
+ * read: When you have multiple heads, take the last one
*
* @return The name of the sheet header
*/
diff --git a/src/main/java/com/alibaba/excel/cache/Ehcache.java b/src/main/java/com/alibaba/excel/cache/Ehcache.java
index 4e757fcd..a5250900 100644
--- a/src/main/java/com/alibaba/excel/cache/Ehcache.java
+++ b/src/main/java/com/alibaba/excel/cache/Ehcache.java
@@ -1,50 +1,49 @@
package com.alibaba.excel.cache;
import java.io.File;
-import java.util.HashMap;
+import java.util.ArrayList;
import java.util.UUID;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.util.FileUtils;
+import com.alibaba.excel.util.ListUtils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
import org.ehcache.CacheManager;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.alibaba.excel.context.AnalysisContext;
-import com.alibaba.excel.util.CollectionUtils;
-import com.alibaba.excel.util.FileUtils;
/**
* Default cache
*
* @author Jiaju Zhuang
*/
+@Slf4j
public class Ehcache implements ReadCache {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(Ehcache.class);
- private static final int BATCH_COUNT = 1000;
- private static final int DEBUG_WRITE_SIZE = 100 * 10000;
- private static final int DEBUG_CACHE_MISS_SIZE = 1000;
+ public static final int BATCH_COUNT = 1000;
/**
* Key index
*/
- private int index = 0;
- private HashMap dataMap = new HashMap(BATCH_COUNT * 4 / 3 + 1);
- private static CacheManager fileCacheManager;
- private static CacheConfiguration fileCacheConfiguration;
- private static CacheManager activeCacheManager;
- private CacheConfiguration activeCacheConfiguration;
+ private int activeIndex = 0;
+ public static final int DEBUG_CACHE_MISS_SIZE = 1000;
+ public static final int DEBUG_WRITE_SIZE = 100 * 10000;
+ private ArrayList dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
+ private static final CacheManager FILE_CACHE_MANAGER;
+ private static final CacheConfiguration FILE_CACHE_CONFIGURATION;
+ private static final CacheManager ACTIVE_CACHE_MANAGER;
+ private final CacheConfiguration activeCacheConfiguration;
/**
* Bulk storage data
*/
- private org.ehcache.Cache fileCache;
+ private org.ehcache.Cache fileCache;
/**
* Currently active cache
*/
- private org.ehcache.Cache activeCache;
+ private org.ehcache.Cache activeCache;
private String cacheAlias;
/**
* Count the number of cache misses
@@ -53,7 +52,7 @@ public class Ehcache implements ReadCache {
public Ehcache(int maxCacheActivateSize) {
activeCacheConfiguration = CacheConfigurationBuilder
- .newCacheConfigurationBuilder(Integer.class, HashMap.class,
+ .newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(maxCacheActivateSize, MemoryUnit.MB))
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(maxCacheActivateSize, MemoryUnit.MB)
.build();
@@ -61,11 +60,11 @@ public class Ehcache implements ReadCache {
static {
File cacheFile = FileUtils.createCacheTmpFile();
- fileCacheManager =
+ FILE_CACHE_MANAGER =
CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(cacheFile)).build(true);
- activeCacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(true);
- fileCacheConfiguration = CacheConfigurationBuilder
- .newCacheConfigurationBuilder(Integer.class, HashMap.class,
+ ACTIVE_CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder().build(true);
+ FILE_CACHE_CONFIGURATION = CacheConfigurationBuilder
+ .newCacheConfigurationBuilder(Integer.class, ArrayList.class,
ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.GB))
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(10, MemoryUnit.GB).build();
}
@@ -73,21 +72,22 @@ public class Ehcache implements ReadCache {
@Override
public void init(AnalysisContext analysisContext) {
cacheAlias = UUID.randomUUID().toString();
- fileCache = fileCacheManager.createCache(cacheAlias, fileCacheConfiguration);
- activeCache = activeCacheManager.createCache(cacheAlias, activeCacheConfiguration);
+ fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
+ activeCache = ACTIVE_CACHE_MANAGER.createCache(cacheAlias, activeCacheConfiguration);
}
@Override
public void put(String value) {
- dataMap.put(index, value);
- if ((index + 1) % BATCH_COUNT == 0) {
- fileCache.put(index / BATCH_COUNT, dataMap);
- dataMap = new HashMap(BATCH_COUNT * 4 / 3 + 1);
+ dataList.add(value);
+ if (dataList.size() >= BATCH_COUNT) {
+ fileCache.put(activeIndex, dataList);
+ activeIndex++;
+ dataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
- index++;
- if (LOGGER.isDebugEnabled()) {
- if (index % DEBUG_WRITE_SIZE == 0) {
- LOGGER.debug("Already put :{}", index);
+ if (log.isDebugEnabled()) {
+ int alreadyPut = activeIndex * BATCH_COUNT + dataList.size();
+ if (alreadyPut % DEBUG_WRITE_SIZE == 0) {
+ log.debug("Already put :{}", alreadyPut);
}
}
}
@@ -98,31 +98,31 @@ public class Ehcache implements ReadCache {
return null;
}
int route = key / BATCH_COUNT;
- HashMap dataMap = activeCache.get(route);
- if (dataMap == null) {
- dataMap = fileCache.get(route);
- activeCache.put(route, dataMap);
- if (LOGGER.isDebugEnabled()) {
+ ArrayList dataList = activeCache.get(route);
+ if (dataList == null) {
+ dataList = fileCache.get(route);
+ activeCache.put(route, dataList);
+ if (log.isDebugEnabled()) {
if (cacheMiss++ % DEBUG_CACHE_MISS_SIZE == 0) {
- LOGGER.debug("Cache misses count:{}", cacheMiss);
+ log.debug("Cache misses count:{}", cacheMiss);
}
}
}
- return dataMap.get(key);
+ return dataList.get(key % BATCH_COUNT);
}
@Override
public void putFinished() {
- if (CollectionUtils.isEmpty(dataMap)) {
+ if (CollectionUtils.isEmpty(dataList)) {
return;
}
- fileCache.put(index / BATCH_COUNT, dataMap);
+ fileCache.put(activeIndex, dataList);
}
@Override
public void destroy() {
- fileCacheManager.removeCache(cacheAlias);
- activeCacheManager.removeCache(cacheAlias);
+ FILE_CACHE_MANAGER.removeCache(cacheAlias);
+ ACTIVE_CACHE_MANAGER.removeCache(cacheAlias);
}
}
diff --git a/src/main/java/com/alibaba/excel/cache/MapCache.java b/src/main/java/com/alibaba/excel/cache/MapCache.java
index ae948fbc..f83a1233 100644
--- a/src/main/java/com/alibaba/excel/cache/MapCache.java
+++ b/src/main/java/com/alibaba/excel/cache/MapCache.java
@@ -1,26 +1,24 @@
package com.alibaba.excel.cache;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
import com.alibaba.excel.context.AnalysisContext;
/**
- *
* Putting temporary data directly into a map is a little more efficient but very memory intensive
*
* @author Jiaju Zhuang
*/
public class MapCache implements ReadCache {
- private Map cache = new HashMap();
- private int index = 0;
+ private List cache = new ArrayList<>();
@Override
public void init(AnalysisContext analysisContext) {}
@Override
public void put(String value) {
- cache.put(index++, value);
+ cache.add(value);
}
@Override
diff --git a/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java b/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
index 95eb0b8f..b742cb6c 100644
--- a/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
+++ b/src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
@@ -17,7 +17,9 @@ import java.util.Locale;
**/
public class BuiltinFormats {
- private static final String[] BUILTIN_FORMATS_CN = {
+ public static short GENERAL = 0;
+
+ public static final String[] BUILTIN_FORMATS_CN = {
// 0
"General",
// 1
@@ -189,7 +191,7 @@ public class BuiltinFormats {
// end
};
- private static final String[] BUILTIN_FORMATS_US = {
+ public static final String[] BUILTIN_FORMATS_US = {
// 0
"General",
// 1
@@ -361,7 +363,7 @@ public class BuiltinFormats {
// end
};
- public static String getBuiltinFormat(Integer index, String defaultFormat, Locale locale) {
+ public static String getBuiltinFormat(Short index, String defaultFormat, Locale locale) {
String[] builtinFormat = switchBuiltinFormats(locale);
if (index == null || index < 0 || index >= builtinFormat.length) {
return defaultFormat;
diff --git a/src/main/java/com/alibaba/excel/constant/OrderConstant.java b/src/main/java/com/alibaba/excel/constant/OrderConstant.java
new file mode 100644
index 00000000..a955025c
--- /dev/null
+++ b/src/main/java/com/alibaba/excel/constant/OrderConstant.java
@@ -0,0 +1,13 @@
+package com.alibaba.excel.constant;
+
+/**
+ * Order constant.
+ *
+ * @author Jiaju Zhuang
+ */
+public class OrderConstant {
+ /**
+ * Sorting of styles written to cells.
+ */
+ public static final int FILL_DATA_FORMAT = 10000;
+}
diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
index c1f89f02..648a7fe9 100644
--- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
+++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java
@@ -6,22 +6,6 @@ import java.io.OutputStream;
import java.util.Map;
import java.util.UUID;
-import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.poifs.crypt.EncryptionInfo;
-import org.apache.poi.poifs.crypt.EncryptionMode;
-import org.apache.poi.poifs.crypt.Encryptor;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.metadata.CellData;
@@ -42,6 +26,22 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.property.ExcelWriteHeadProperty;
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageAccess;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.EncryptionMode;
+import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* A context is the main anchorage point of a excel writer.
*
@@ -50,6 +50,7 @@ import com.alibaba.excel.write.property.ExcelWriteHeadProperty;
public class WriteContextImpl implements WriteContext {
private static final Logger LOGGER = LoggerFactory.getLogger(WriteContextImpl.class);
+ private static final String NO_SHEETS="no sheets";
/**
* The Workbook currently written
@@ -178,8 +179,12 @@ public class WriteContextImpl implements WriteContext {
writeSheetHolder
.setCachedSheet(writeWorkbookHolder.getCachedWorkbook().getSheet(writeSheetHolder.getSheetName()));
}
- } catch (Exception e) {
- currentSheet = createSheet();
+ } catch (IllegalArgumentException e) {
+ if (e.getMessage() != null && e.getMessage().contains(NO_SHEETS)) {
+ currentSheet = createSheet();
+ } else {
+ throw e;
+ }
}
if (currentSheet == null) {
currentSheet = createSheet();
diff --git a/src/main/java/com/alibaba/excel/converters/AutoConverter.java b/src/main/java/com/alibaba/excel/converters/AutoConverter.java
index 800d2d85..07ad471f 100644
--- a/src/main/java/com/alibaba/excel/converters/AutoConverter.java
+++ b/src/main/java/com/alibaba/excel/converters/AutoConverter.java
@@ -10,10 +10,10 @@ import com.alibaba.excel.metadata.property.ExcelContentProperty;
*
* @author Jiaju Zhuang
*/
-public class AutoConverter implements Converter {
+public class AutoConverter implements Converter