Browse Source

修改07在特殊情况下用`String`接收数字会丢小数位的bug

pull/1688/head
Jiaju Zhuang 4 years ago
parent
commit
7e6d81c5e0
  1. 2
      pom.xml
  2. 78
      src/main/java/com/alibaba/excel/metadata/format/DataFormatter.java
  3. 5
      src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java
  4. 3
      update.md

2
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId> <artifactId>easyexcel</artifactId>
<version>2.2.6</version> <version>2.2.7</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>easyexcel</name> <name>easyexcel</name>

78
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.Matcher;
import java.util.regex.Pattern; 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.DateUtil;
import org.apache.poi.ss.usermodel.ExcelStyleDateFormatter; import org.apache.poi.ss.usermodel.ExcelStyleDateFormatter;
import org.apache.poi.ss.usermodel.FractionFormat; import org.apache.poi.ss.usermodel.FractionFormat;
@ -168,22 +170,58 @@ public class DataFormatter {
this.decimalSymbols = DecimalFormatSymbols.getInstance(this.locale); 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 // See if we already have it cached
Format format = formats.get(dataFormatString); Format format = formats.get(formatStr);
if (format != null) { if (format != null) {
return format; return format;
} }
// Is it one of the special built in types, General or @? // 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(); format = getDefaultFormat();
addFormat(dataFormatString, format); addFormat(formatStr, format);
return format; return format;
} }
// Build a formatter, and cache it // Build a formatter, and cache it
format = createFormat(dataFormat, dataFormatString); format = createFormat(dataFormat, formatStr);
addFormat(dataFormatString, format); addFormat(formatStr, format);
return format; return format;
} }
@ -530,7 +568,7 @@ public class DataFormatter {
try { try {
return new InternalDecimalFormatWithScale(format, symbols); return new InternalDecimalFormatWithScale(format, symbols);
} catch (IllegalArgumentException iae) { } 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, // the pattern could not be parsed correctly,
// so fall back to the default number format // so fall back to the default number format
return getDefaultFormat(); return getDefaultFormat();
@ -570,7 +608,7 @@ public class DataFormatter {
* @return Formatted value * @return Formatted value
*/ */
private String getFormattedDateString(Double data, Integer dataFormat, String dataFormatString) { private String getFormattedDateString(Double data, Integer dataFormat, String dataFormatString) {
Format dateFormat = getFormat(dataFormat, dataFormatString); Format dateFormat = getFormat(data, dataFormat, dataFormatString);
if (dateFormat instanceof ExcelStyleDateFormatter) { if (dateFormat instanceof ExcelStyleDateFormatter) {
// Hint about the raw excel value // Hint about the raw excel value
((ExcelStyleDateFormatter)dateFormat).setDateToBeFormatted(data); ((ExcelStyleDateFormatter)dateFormat).setDateToBeFormatted(data);
@ -593,7 +631,7 @@ public class DataFormatter {
* @return a formatted number string * @return a formatted number string
*/ */
private String getFormattedNumberString(Double data, Integer dataFormat, String dataFormatString) { private String getFormattedNumberString(Double data, Integer dataFormat, String dataFormatString) {
Format numberFormat = getFormat(dataFormat, dataFormatString); Format numberFormat = getFormat(data, dataFormat, dataFormatString);
String formatted = numberFormat.format(data); String formatted = numberFormat.format(data);
return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation return formatted.replaceFirst("E(\\d)", "E+$1"); // to match Excel's E-notation
} }
@ -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
}
}
} }

5
src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java

@ -33,9 +33,10 @@ public class Lock2Test {
@Test @Test
public void test() throws Exception { public void test() throws Exception {
File file = TestFileUtil.readUserHomeFile("test/test6.xls"); // File file = TestFileUtil.readUserHomeFile("test/test6.xls");
File file = new File("D:\\test\\T85_税金入库表202010.xlsx");
List<Object> list = EasyExcel.read(file).sheet(1).headRowNumber(0).doReadSync(); List<Object> list = EasyExcel.read(file).sheet(0).headRowNumber(0).doReadSync();
LOGGER.info("数据:{}", list.size()); LOGGER.info("数据:{}", list.size());
for (Object data : list) { for (Object data : list) {
LOGGER.info("返回数据:{}", JSON.toJSONString(data)); LOGGER.info("返回数据:{}", JSON.toJSONString(data));

3
update.md

@ -1,3 +1,6 @@
# 2.2.6
* 修改07在特殊情况下用`String`接收数字会丢小数位的bug
# 2.2.6 # 2.2.6
* 修改跳着读取03版本空指针bug * 修改跳着读取03版本空指针bug

Loading…
Cancel
Save