diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
index f5d4b69..31362d3 100644
--- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
+++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
@@ -35,25 +35,20 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
}
}
- private void choiceExcelExecutor() {
- try {
- ExcelTypeEnum excelType = analysisContext.readWorkbookHolder().getExcelType();
- if (excelType == null) {
+ private void choiceExcelExecutor() throws Exception {
+ ExcelTypeEnum excelType = analysisContext.readWorkbookHolder().getExcelType();
+ if (excelType == null) {
+ excelExecutor = new XlsxSaxAnalyser(analysisContext);
+ return;
+ }
+ switch (excelType) {
+ case XLS:
+ excelExecutor = new XlsSaxAnalyser(analysisContext);
+ break;
+ case XLSX:
excelExecutor = new XlsxSaxAnalyser(analysisContext);
- return;
- }
- switch (excelType) {
- case XLS:
- excelExecutor = new XlsSaxAnalyser(analysisContext);
- break;
- case XLSX:
- excelExecutor = new XlsxSaxAnalyser(analysisContext);
- break;
- default:
- }
- } catch (Exception e) {
- throw new ExcelAnalysisException("File type error,io must be available markSupported,you can do like "
- + "this new BufferedInputStream(new FileInputStream(\\\"/xxxx\\\"))
\"", e);
+ break;
+ default:
}
}
diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java
index 40793df..f8899c0 100644
--- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java
@@ -1,12 +1,17 @@
package com.alibaba.excel.analysis.v03.handlers;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
+import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.v03.AbstractXlsRecordHandler;
+import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
/**
@@ -15,9 +20,13 @@ import com.alibaba.excel.metadata.CellData;
* @author Dan Zheng
*/
public class FormulaRecordHandler extends AbstractXlsRecordHandler {
+ private static final Logger LOGGER = LoggerFactory.getLogger(FormulaRecordHandler.class);
+
+ private static final String ERROR = "#VALUE!";
private int nextRow;
private int nextColumn;
private boolean outputNextStringRecord;
+ private CellData tempCellData;
private FormatTrackingHSSFListener formatListener;
private HSSFWorkbook stubWorkbook;
@@ -38,24 +47,56 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler {
this.row = frec.getRow();
this.column = frec.getColumn();
-
- if (Double.isNaN(frec.getValue())) {
- // Formula result is a string
- // This is stored in the next record
- outputNextStringRecord = true;
- nextRow = frec.getRow();
- nextColumn = frec.getColumn();
- } else {
- this.cellData = new CellData(frec.getValue());
+ CellType cellType = CellType.forInt(frec.getCachedResultType());
+ String formulaValue = null;
+ try {
+ formulaValue = HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression());
+ } catch (Exception e) {
+ LOGGER.warn("Get formula value error.{}", e.getMessage());
+ }
+ switch (cellType) {
+ case STRING:
+ // Formula result is a string
+ // This is stored in the next record
+ outputNextStringRecord = true;
+ nextRow = frec.getRow();
+ nextColumn = frec.getColumn();
+ tempCellData = new CellData(CellDataTypeEnum.STRING);
+ tempCellData.setFormula(Boolean.TRUE);
+ tempCellData.setFormulaValue(formulaValue);
+ break;
+ case NUMERIC:
+ this.cellData = new CellData(frec.getValue());
+ this.cellData.setFormula(Boolean.TRUE);
+ this.cellData.setFormulaValue(formulaValue);
+ break;
+ case ERROR:
+ this.cellData = new CellData(CellDataTypeEnum.ERROR);
+ this.cellData.setStringValue(ERROR);
+ this.cellData.setFormula(Boolean.TRUE);
+ this.cellData.setFormulaValue(formulaValue);
+ break;
+ case BOOLEAN:
+ this.cellData = new CellData(frec.getCachedBooleanValue());
+ this.cellData.setFormula(Boolean.TRUE);
+ this.cellData.setFormulaValue(formulaValue);
+ break;
+ default:
+ this.cellData = new CellData(CellDataTypeEnum.EMPTY);
+ this.cellData.setFormula(Boolean.TRUE);
+ this.cellData.setFormulaValue(formulaValue);
+ break;
}
} else if (record.getSid() == StringRecord.sid) {
if (outputNextStringRecord) {
// String for formula
StringRecord srec = (StringRecord)record;
- this.cellData = new CellData(srec.getString());
+ this.cellData = tempCellData;
+ this.cellData.setStringValue(srec.getString());
this.row = nextRow;
this.column = nextColumn;
outputNextStringRecord = false;
+ tempCellData = null;
}
}
}
diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
index a59060f..a480276 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java
@@ -13,17 +13,21 @@ import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import com.alibaba.excel.analysis.ExcelExecutor;
import com.alibaba.excel.cache.Ehcache;
+import com.alibaba.excel.cache.MapCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.read.metadata.ReadSheet;
@@ -35,6 +39,11 @@ import com.alibaba.excel.util.FileUtils;
* @author jipengfei
*/
public class XlsxSaxAnalyser implements ExcelExecutor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(XlsxSaxAnalyser.class);
+ /**
+ * If it's less than 5M, use map cache, or use ehcache.
+ */
+ private static final long USE_MAP_CACHE_SIZE = 5 * 1000 * 1000L;
private AnalysisContext analysisContext;
private List sheetList;
private Map sheetMap;
@@ -43,15 +52,32 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
this.analysisContext = analysisContext;
// Initialize cache
ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder();
+
+ OPCPackage pkg = readOpcPackage(readWorkbookHolder);
+
+ PackagePart sharedStringsTablePackagePart =
+ pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType()).get(0);
if (readWorkbookHolder.getReadCache() == null) {
- readWorkbookHolder.setReadCache(new Ehcache());
+ long size = sharedStringsTablePackagePart.getSize();
+ if (size < 0) {
+ size = sharedStringsTablePackagePart.getInputStream().available();
+ }
+ if (size < USE_MAP_CACHE_SIZE) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.info("Use map cache.size:{}", size);
+ }
+ readWorkbookHolder.setReadCache(new MapCache());
+ } else {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.info("Use ehcache.size:{}", size);
+ }
+ readWorkbookHolder.setReadCache(new Ehcache());
+ }
}
readWorkbookHolder.getReadCache().init(analysisContext);
- OPCPackage pkg = readOpcPackage(readWorkbookHolder);
-
// Analysis sharedStringsTable.xml
- analysisSharedStringsTable(pkg, readWorkbookHolder);
+ analysisSharedStringsTable(sharedStringsTablePackagePart.getInputStream(), readWorkbookHolder);
XSSFReader xssfReader = new XSSFReader(pkg);
@@ -88,10 +114,10 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
}
}
- private void analysisSharedStringsTable(OPCPackage pkg, ReadWorkbookHolder readWorkbookHolder) throws Exception {
+ private void analysisSharedStringsTable(InputStream sharedStringsTableInputStream,
+ ReadWorkbookHolder readWorkbookHolder) throws Exception {
ContentHandler handler = new SharedStringsTableHandler(readWorkbookHolder.getReadCache());
- parseXmlSource(pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType()).get(0).getInputStream(),
- handler);
+ parseXmlSource(sharedStringsTableInputStream, handler);
readWorkbookHolder.getReadCache().putFinished();
}
@@ -105,7 +131,7 @@ public class XlsxSaxAnalyser implements ExcelExecutor {
File readTempFile = FileUtils.createCacheTmpFile();
readWorkbookHolder.setTempFile(readTempFile);
File tempFile = new File(readTempFile.getPath(), UUID.randomUUID().toString() + ".xlsx");
- FileUtils.writeToFile(readTempFile, readWorkbookHolder.getInputStream());
+ FileUtils.writeToFile(tempFile, readWorkbookHolder.getInputStream());
return OPCPackage.open(tempFile);
}
diff --git a/src/main/java/com/alibaba/excel/metadata/CellData.java b/src/main/java/com/alibaba/excel/metadata/CellData.java
index 5f9ced7..dfef257 100644
--- a/src/main/java/com/alibaba/excel/metadata/CellData.java
+++ b/src/main/java/com/alibaba/excel/metadata/CellData.java
@@ -24,6 +24,15 @@ public class CellData {
private Boolean formula;
private String formulaValue;
+ public CellData(CellData other) {
+ this.type = other.type;
+ this.doubleValue = other.doubleValue;
+ this.stringValue = other.stringValue;
+ this.booleanValue = other.booleanValue;
+ this.formula = other.formula;
+ this.formulaValue = other.formulaValue;
+ }
+
public CellData(String stringValue) {
this(CellDataTypeEnum.STRING, stringValue);
}
@@ -128,4 +137,5 @@ public class CellData {
return "empty";
}
}
+
}
diff --git a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java
index 7285808..80deec4 100644
--- a/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java
+++ b/src/main/java/com/alibaba/excel/read/listener/ModelBuildEventListener.java
@@ -82,7 +82,7 @@ public class ModelBuildEventListener extends AbstractIgnoreExceptionReadListener
private Object convertValue(CellData cellData, Class clazz, ExcelContentProperty contentProperty,
Map converterMap, GlobalConfiguration globalConfiguration) {
if (clazz == CellData.class) {
- return cellData;
+ return new CellData(cellData);
}
Converter converter = null;
if (contentProperty != null) {
diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java
index 0962edf..c2a9407 100644
--- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java
+++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java
@@ -3,6 +3,9 @@ package com.alibaba.excel.read.metadata.holder;
import java.io.File;
import java.io.InputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.alibaba.excel.cache.ReadCache;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.HolderEnum;
@@ -17,6 +20,8 @@ import com.alibaba.excel.support.ExcelTypeEnum;
* @author zhuangjiaju
*/
public class ReadWorkbookHolder extends AbstractReadHolder {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ReadWorkbookHolder.class);
+
/**
* current param
*/
@@ -94,8 +99,14 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
} else {
this.excelType = readWorkbook.getExcelType();
}
+ if (ExcelTypeEnum.XLS == excelType && getGlobalConfiguration().getUse1904windowing() == null) {
+ getGlobalConfiguration().setUse1904windowing(Boolean.FALSE);
+ }
this.customObject = readWorkbook.getCustomObject();
this.readCache = readWorkbook.getReadCache();
+ if (readCache != null && ExcelTypeEnum.XLS == excelType) {
+ LOGGER.warn("Xls not support 'readCache'!");
+ }
}
public ReadWorkbook getReadWorkbook() {
diff --git a/src/main/java/com/alibaba/excel/util/FileUtils.java b/src/main/java/com/alibaba/excel/util/FileUtils.java
index 52353d1..0a76a65 100644
--- a/src/main/java/com/alibaba/excel/util/FileUtils.java
+++ b/src/main/java/com/alibaba/excel/util/FileUtils.java
@@ -8,6 +8,7 @@ import java.io.OutputStream;
import java.util.UUID;
import com.alibaba.excel.exception.ExcelAnalysisException;
+import com.alibaba.excel.exception.ExcelGenerateException;
/**
*
@@ -24,7 +25,7 @@ public class FileUtils {
/**
* Write inputStream to file
- *
+ *
* @param file
* @param inputStream
*/
@@ -65,12 +66,16 @@ public class FileUtils {
public static File createCacheTmpFile() {
File directory = createTmpDirectory(CACHE);
- return new File(directory.getPath(), UUID.randomUUID().toString());
+ File cache = new File(directory.getPath(), UUID.randomUUID().toString());
+ if (!cache.mkdir()) {
+ throw new ExcelGenerateException("Can not create temp file!");
+ }
+ return cache;
}
/**
* delete file
- *
+ *
* @param file
*/
public static void delete(File file) {
diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java
index 19e4b28..ae797bf 100644
--- a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java
+++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterData.java
@@ -36,10 +36,10 @@ public class ReadAllConverterData {
private Short shortBoolean;
private Short shortNumber;
private Short shortString;
- private String StringBoolean;
- private String StringNumber;
- private String StringString;
- private String StringError;
- private String StringFormulaNumber;
- private String StringFormulaString;
+ private String stringBoolean;
+ private String stringNumber;
+ private String stringString;
+ private String stringError;
+ private String stringFormulaNumber;
+ private String stringFormulaString;
}
diff --git a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java
index 6335246..0bc7da9 100644
--- a/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java
+++ b/src/test/java/com/alibaba/easyexcel/test/core/converter/ReadAllConverterDataListener.java
@@ -1,5 +1,7 @@
package com.alibaba.easyexcel.test.core.converter;
+import java.math.BigDecimal;
+import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
@@ -9,6 +11,8 @@ import org.slf4j.LoggerFactory;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.exception.ExcelCommonException;
+import com.alibaba.excel.util.DateUtils;
import com.alibaba.fastjson.JSON;
/**
@@ -27,20 +31,41 @@ public class ReadAllConverterDataListener extends AnalysisEventListener