diff --git a/pom.xml b/pom.xml
index 831caff..9f1a4c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.alibaba
easyexcel
- 2.2.6
+ 2.2.10
jar
easyexcel
diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java
index 3521e46..580e670 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/AbstractCellValueTagHandler.java
@@ -7,6 +7,7 @@ import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder;
import com.alibaba.excel.util.BooleanUtils;
+import com.alibaba.excel.util.StringUtils;
/**
* Cell Value Handler
@@ -20,6 +21,7 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
CellData tempCellData = xlsxReadSheetHolder.getTempCellData();
StringBuilder tempData = xlsxReadSheetHolder.getTempData();
+ String tempDataString = tempData.toString();
CellDataTypeEnum oldType = tempCellData.getType();
switch (oldType) {
case DIRECT_STRING:
@@ -28,12 +30,20 @@ public abstract class AbstractCellValueTagHandler extends AbstractXlsxTagHandler
tempCellData.setStringValue(tempData.toString());
break;
case BOOLEAN:
+ if(StringUtils.isEmpty(tempDataString)){
+ tempCellData.setType(CellDataTypeEnum.EMPTY);
+ break;
+ }
tempCellData.setBooleanValue(BooleanUtils.valueOf(tempData.toString()));
break;
case NUMBER:
case EMPTY:
+ if(StringUtils.isEmpty(tempDataString)){
+ tempCellData.setType(CellDataTypeEnum.EMPTY);
+ break;
+ }
tempCellData.setType(CellDataTypeEnum.NUMBER);
- tempCellData.setNumberValue(new BigDecimal(tempData.toString()));
+ tempCellData.setNumberValue(BigDecimal.valueOf(Double.parseDouble(tempDataString)));
break;
default:
throw new IllegalStateException("Cannot set values now");
diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java
index 09c9264..7e685c9 100644
--- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java
+++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/CellValueTagHandler.java
@@ -3,6 +3,7 @@ package com.alibaba.excel.analysis.v07.handlers;
import com.alibaba.excel.context.xlsx.XlsxReadContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.util.StringUtils;
/**
* Cell Value Handler
@@ -17,6 +18,10 @@ public class CellValueTagHandler extends AbstractCellValueTagHandler {
CellData tempCellData = xlsxReadContext.xlsxReadSheetHolder().getTempCellData();
switch (tempCellData.getType()) {
case STRING:
+ // In some cases, although cell type is a string, it may be an empty tag
+ if(StringUtils.isEmpty(tempCellData.getStringValue())){
+ break;
+ }
String stringValue = xlsxReadContext.readWorkbookHolder().getReadCache()
.get(Integer.valueOf(tempCellData.getStringValue()));
if (stringValue != null && xlsxReadContext.currentReadHolder().globalConfiguration().getAutoTrim()) {
diff --git a/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java b/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java
index b31bc70..693c112 100644
--- a/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java
+++ b/src/main/java/com/alibaba/excel/converters/string/StringNumberConverter.java
@@ -47,7 +47,7 @@ public class StringNumberConverter implements Converter {
}
// Excel defines formatting
if (cellData.getDataFormat() != null && !StringUtils.isEmpty(cellData.getDataFormatString())) {
- return NumberDataFormatterUtils.format(cellData.getNumberValue().doubleValue(), cellData.getDataFormat(),
+ return NumberDataFormatterUtils.format(cellData.getNumberValue(), cellData.getDataFormat(),
cellData.getDataFormatString(), globalConfiguration);
}
// Default conversion number
diff --git a/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java b/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java
index 0bc70d1..2c955ed 100644
--- a/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java
+++ b/src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java
@@ -34,6 +34,8 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.poi.ss.format.CellFormat;
+import org.apache.poi.ss.format.CellFormatResult;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.ExcelStyleDateFormatter;
import org.apache.poi.ss.usermodel.FractionFormat;
@@ -168,22 +170,58 @@ public class DataFormatter {
this.decimalSymbols = DecimalFormatSymbols.getInstance(this.locale);
}
- private Format getFormat(Integer dataFormat, String dataFormatString) {
+ private Format getFormat(Double data,Integer dataFormat, String dataFormatString) {
+
+ // Might be better to separate out the n p and z formats, falling back to p when n and z are not set.
+ // That however would require other code to be re factored.
+ // String[] formatBits = formatStrIn.split(";");
+ // int i = cellValue > 0.0 ? 0 : cellValue < 0.0 ? 1 : 2;
+ // String formatStr = (i < formatBits.length) ? formatBits[i] : formatBits[0];
+ String formatStr = dataFormatString;
+
+ // Excel supports 2+ part conditional data formats, eg positive/negative/zero,
+ // or (>1000),(>0),(0),(negative). As Java doesn't handle these kinds
+ // of different formats for different ranges, just +ve/-ve, we need to
+ // handle these ourselves in a special way.
+ // For now, if we detect 2+ parts, we call out to CellFormat to handle it
+ // TODO Going forward, we should really merge the logic between the two classes
+ if (formatStr.contains(";") &&
+ (formatStr.indexOf(';') != formatStr.lastIndexOf(';')
+ || rangeConditionalPattern.matcher(formatStr).matches()
+ ) ) {
+ try {
+ // Ask CellFormat to get a formatter for it
+ CellFormat cfmt = CellFormat.getInstance(locale, formatStr);
+ // CellFormat requires callers to identify date vs not, so do so
+ Object cellValueO = data;
+ if (DateUtil.isADateFormat(dataFormat, formatStr) &&
+ // don't try to handle Date value 0, let a 3 or 4-part format take care of it
+ data.doubleValue() != 0.0) {
+ cellValueO = DateUtil.getJavaDate(data, use1904windowing);
+ }
+ // Wrap and return (non-cachable - CellFormat does that)
+ return new CellFormatResultWrapper( cfmt.apply(cellValueO) );
+ } catch (Exception e) {
+ LOGGER.warn("Formatting failed for format {}, falling back",formatStr, e);
+ }
+ }
+
// See if we already have it cached
- Format format = formats.get(dataFormatString);
+ Format format = formats.get(formatStr);
if (format != null) {
return format;
}
+
// Is it one of the special built in types, General or @?
- if ("General".equalsIgnoreCase(dataFormatString) || "@".equals(dataFormatString)) {
+ if ("General".equalsIgnoreCase(formatStr) || "@".equals(formatStr)) {
format = getDefaultFormat();
- addFormat(dataFormatString, format);
+ addFormat(formatStr, format);
return format;
}
// Build a formatter, and cache it
- format = createFormat(dataFormat, dataFormatString);
- addFormat(dataFormatString, format);
+ format = createFormat(dataFormat, formatStr);
+ addFormat(formatStr, format);
return format;
}
@@ -530,7 +568,7 @@ public class DataFormatter {
try {
return new InternalDecimalFormatWithScale(format, symbols);
} catch (IllegalArgumentException iae) {
- LOGGER.debug("Formatting failed for format {}, falling back", formatStr, iae);
+ LOGGER.error("Formatting failed for format {}, falling back", formatStr, iae);
// the pattern could not be parsed correctly,
// so fall back to the default number format
return getDefaultFormat();
@@ -570,7 +608,7 @@ public class DataFormatter {
* @return Formatted value
*/
private String getFormattedDateString(Double data, Integer dataFormat, String dataFormatString) {
- Format dateFormat = getFormat(dataFormat, dataFormatString);
+ Format dateFormat = getFormat(data, dataFormat, dataFormatString);
if (dateFormat instanceof ExcelStyleDateFormatter) {
// Hint about the raw excel value
((ExcelStyleDateFormatter)dateFormat).setDateToBeFormatted(data);
@@ -592,8 +630,8 @@ public class DataFormatter {
* @param dataFormatString
* @return a formatted number string
*/
- private String getFormattedNumberString(Double data, Integer dataFormat, String dataFormatString) {
- Format numberFormat = getFormat(dataFormat, dataFormatString);
+ private String getFormattedNumberString(BigDecimal data, Integer dataFormat, String dataFormatString) {
+ Format numberFormat = getFormat(data.doubleValue(), dataFormat, dataFormatString);
String formatted = numberFormat.format(data);
return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation
}
@@ -606,9 +644,9 @@ public class DataFormatter {
* @param dataFormatString
* @return
*/
- public String format(Double data, Integer dataFormat, String dataFormatString) {
+ public String format(BigDecimal data, Integer dataFormat, String dataFormatString) {
if (DateUtils.isADateFormat(dataFormat, dataFormatString)) {
- return getFormattedDateString(data, dataFormat, dataFormatString);
+ return getFormattedDateString(data.doubleValue(), dataFormat, dataFormatString);
}
return getFormattedNumberString(data, dataFormat, dataFormatString);
}
@@ -794,4 +832,26 @@ public class DataFormatter {
}
}
+ /**
+ * Workaround until we merge {@link org.apache.poi.ss.usermodel.DataFormatter} with {@link CellFormat}. Constant, non-cachable wrapper around a
+ * {@link CellFormatResult}
+ */
+ private final class CellFormatResultWrapper extends Format {
+ private final CellFormatResult result;
+
+ private CellFormatResultWrapper(CellFormatResult result) {
+ this.result = result;
+ }
+
+ @Override
+ public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
+ return toAppendTo.append(result.text.trim());
+ }
+
+ @Override
+ public Object parseObject(String source, ParsePosition pos) {
+ return null; // Not supported
+ }
+ }
+
}
diff --git a/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java b/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java
index 09d149b..b4ba5b0 100644
--- a/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java
+++ b/src/main/java/com/alibaba/excel/util/NumberDataFormatterUtils.java
@@ -1,5 +1,7 @@
package com.alibaba.excel.util;
+import java.math.BigDecimal;
+
import com.alibaba.excel.metadata.format.DataFormatter;
import com.alibaba.excel.metadata.GlobalConfiguration;
@@ -24,7 +26,7 @@ public class NumberDataFormatterUtils {
* @param globalConfiguration
* @return
*/
- public static String format(Double data, Integer dataFormat, String dataFormatString,
+ public static String format(BigDecimal data, Integer dataFormat, String dataFormatString,
GlobalConfiguration globalConfiguration) {
DataFormatter dataFormatter = DATA_FORMATTER_THREAD_LOCAL.get();
if (dataFormatter == null) {
diff --git a/src/test/java/com/alibaba/easyexcel/test/core/dataformat/DateFormatTest.java b/src/test/java/com/alibaba/easyexcel/test/core/dataformat/DateFormatTest.java
index f1de542..d0c308a 100644
--- a/src/test/java/com/alibaba/easyexcel/test/core/dataformat/DateFormatTest.java
+++ b/src/test/java/com/alibaba/easyexcel/test/core/dataformat/DateFormatTest.java
@@ -4,17 +4,16 @@ import java.io.File;
import java.util.List;
import java.util.Locale;
+import com.alibaba.easyexcel.test.util.TestFileUtil;
+import com.alibaba.excel.EasyExcel;
+
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.alibaba.easyexcel.test.util.TestFileUtil;
-import com.alibaba.excel.EasyExcel;
-
/**
- *
* @author Jiaju Zhuang
*/
public class DateFormatTest {
@@ -44,6 +43,14 @@ public class DateFormatTest {
private void readCn(File file) {
List list =
EasyExcel.read(file, DateFormatData.class, null).locale(Locale.CHINA).sheet().doReadSync();
+ for (DateFormatData data : list) {
+ if (data.getDateStringCn() != null && !data.getDateStringCn().equals(data.getDate())) {
+ LOGGER.info("date:cn:{},{}", data.getDateStringCn(), data.getDate());
+ }
+ if (data.getNumberStringCn() != null && !data.getNumberStringCn().equals(data.getNumber())) {
+ LOGGER.info("number:cn{},{}", data.getNumberStringCn(), data.getNumber());
+ }
+ }
for (DateFormatData data : list) {
Assert.assertEquals(data.getDateStringCn(), data.getDate());
Assert.assertEquals(data.getNumberStringCn(), data.getNumber());
@@ -53,6 +60,14 @@ public class DateFormatTest {
private void readUs(File file) {
List list =
EasyExcel.read(file, DateFormatData.class, null).locale(Locale.US).sheet().doReadSync();
+ for (DateFormatData data : list) {
+ if (data.getDateStringUs() != null && !data.getDateStringUs().equals(data.getDate())) {
+ LOGGER.info("date:us:{},{}", data.getDateStringUs(), data.getDate());
+ }
+ if (data.getNumberStringUs() != null && !data.getNumberStringUs().equals(data.getNumber())) {
+ LOGGER.info("number:us{},{}", data.getNumberStringUs(), data.getNumber());
+ }
+ }
for (DateFormatData data : list) {
Assert.assertEquals(data.getDateStringUs(), data.getDate());
Assert.assertEquals(data.getNumberStringUs(), data.getNumber());
diff --git a/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java
index 375f9be..b7f63cf 100644
--- a/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java
+++ b/src/test/java/com/alibaba/easyexcel/test/core/encrypt/EncryptDataTest.java
@@ -3,21 +3,23 @@ package com.alibaba.easyexcel.test.core.encrypt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
-import org.junit.BeforeClass;
-import org.junit.FixMethodOrder;
-import org.junit.Test;
-import org.junit.runners.MethodSorters;
-
import com.alibaba.easyexcel.test.core.simple.SimpleData;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
/**
- *
* @author Jiaju Zhuang
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -28,6 +30,15 @@ public class EncryptDataTest {
private static File file07OutputStream;
private static File file03OutputStream;
+ @Test
+ public void testformat() {
+ DecimalFormat decimalFormat = new DecimalFormat("0.00");
+ decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
+ BigDecimal bigDecimal = new BigDecimal("0.105");
+
+ System.out.println(decimalFormat.format(bigDecimal));
+ }
+
@BeforeClass
public static void init() {
file07 = TestFileUtil.createNewFile("encrypt07.xlsx");
diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java
index 0dcef53..9220264 100644
--- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java
+++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java
@@ -33,9 +33,10 @@ public class Lock2Test {
@Test
public void test() throws Exception {
- File file = TestFileUtil.readUserHomeFile("test/test6.xls");
+// File file = TestFileUtil.readUserHomeFile("test/test6.xls");
+ File file = new File("/Users/zhuangjiaju/test/签到金模板-0507-v5.xlsx");
- List