diff --git a/CHANGELOG.md b/CHANGELOG.md index a4ee8a698..44c9311a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,14 @@ ------------------------------------------------------------------------------------------------------------- -# 5.7.8 (2021-08-08) +# 5.7.8 (2021-08-09) ### 🐣新特性 * 【core 】 MapProxy支持return this的setter方法(pr#392@Gitee) * 【core 】 BeeDSFactory移除sqlite事务修复代码,新版本BeeCP已修复 * 【core 】 增加compress包,扩充Zip操作灵活性 * 【json 】 增加JSONBeanParser +* 【poi 】 增加CellSetter,可以自定义单元格值写出 ### 🐞Bug修复 * 【core 】 改进NumberChineseFormatter算法,补充完整单元测试,解决零问题 diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java index 2d4eb742a..d17e9b9fb 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellEditor.java @@ -3,7 +3,9 @@ package cn.hutool.poi.excel.cell; import org.apache.poi.ss.usermodel.Cell; /** - * 单元格编辑器接口 + * 单元格编辑器接口
+ * 在读取Excel值时,有时我们需要针对所有单元格统一处理结果值(如null转默认值)的情况,实现接口并调用
+ * reader.setCellEditor()设置编辑器 * * @author Looly */ @@ -11,7 +13,7 @@ import org.apache.poi.ss.usermodel.Cell; public interface CellEditor { /** - * 编辑 + * 编辑,根据单元格信息处理结果值,返回处理后的结果 * * @param cell 单元格对象,可以获取单元格行、列样式等信息 * @param value 单元格值 diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellHandler.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellHandler.java index 6488bc9b7..f94bccd26 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellHandler.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellHandler.java @@ -3,7 +3,8 @@ package cn.hutool.poi.excel.cell; import org.apache.poi.ss.usermodel.Cell; /** - * 单元格处理器接口 + * 单元格处理器接口
+ * 用于在读取Excel单元格值时自定义结果值的获取,如在获取值的同时,获取单元格样式、坐标等信息,或根据单元格信息,装饰转换结果值 * * @author Looly */ diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellSetter.java new file mode 100755 index 000000000..2c167431c --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellSetter.java @@ -0,0 +1,19 @@ +package cn.hutool.poi.excel.cell; + +import org.apache.poi.ss.usermodel.Cell; + +/** + * 单元格值自定义设置器,主要用于Excel数据导出,用户通过自定义此接口,实现可定制化的单元格值设定 + * + * @author looly + * @since 5.7.8 + */ +@FunctionalInterface +public interface CellSetter { + + /** + * 自定义单元格值设置,同时可以设置单元格样式、格式等信息 + * @param cell 单元格 + */ + void setValue(Cell cell); +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java index 9e0ffbbb6..6cb0ebce3 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java @@ -1,11 +1,12 @@ package cn.hutool.poi.excel.cell; -import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.poi.excel.ExcelDateUtil; import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.StyleSet; +import cn.hutool.poi.excel.cell.setters.CellSetterFactory; +import cn.hutool.poi.excel.cell.values.ErrorCellValue; +import cn.hutool.poi.excel.cell.values.NumericCellValue; import cn.hutool.poi.excel.editors.TrimEditor; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -14,20 +15,14 @@ import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.FormulaError; -import org.apache.poi.ss.usermodel.RichTextString; 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.ss.util.NumberToTextConverter; import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.ss.util.SheetUtil; import java.math.BigDecimal; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.temporal.TemporalAccessor; import java.util.Calendar; import java.util.Date; @@ -118,21 +113,19 @@ public class CellUtil { Object value; switch (cellType) { case NUMERIC: - value = getNumericValue(cell); + value = new NumericCellValue(cell).getValue(); break; case BOOLEAN: value = cell.getBooleanCellValue(); break; case FORMULA: - // 遇到公式时查找公式结果类型 value = getCellValue(cell, cell.getCachedFormulaResultType(), cellEditor); break; case BLANK: value = StrUtil.EMPTY; break; case ERROR: - final FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); - value = (null == error) ? StrUtil.EMPTY : error.getString(); + value = new ErrorCellValue(cell).getValue(); break; default: value = cell.getStringCellValue(); @@ -193,15 +186,12 @@ public class CellUtil { * @param style 自定义样式,null表示无样式 */ public static void setCellValue(Cell cell, Object value, CellStyle style) { - if (null == cell) { - return; - } - - if (null != style) { - cell.setCellStyle(style); - } - - setCellValue(cell, value); + setCellValue(cell, (CellSetter) cell1 -> { + if (null != style) { + cell1.setCellStyle(style); + setCellValue(cell, value); + } + }); } /** @@ -226,38 +216,7 @@ public class CellUtil { cell.setBlank(); } - if (null == value) { - cell.setCellValue(StrUtil.EMPTY); - } else if (value instanceof FormulaCellValue) { - // 公式 - cell.setCellFormula(((FormulaCellValue) value).getValue()); - } else if (value instanceof Date) { - cell.setCellValue((Date) value); - } else if (value instanceof TemporalAccessor) { - if (value instanceof Instant) { - cell.setCellValue(Date.from((Instant) value)); - } else if (value instanceof LocalDateTime) { - cell.setCellValue((LocalDateTime) value); - } else if (value instanceof LocalDate) { - cell.setCellValue((LocalDate) value); - } - } else if (value instanceof Calendar) { - cell.setCellValue((Calendar) value); - } else if (value instanceof Boolean) { - cell.setCellValue((Boolean) value); - } else if (value instanceof RichTextString) { - cell.setCellValue((RichTextString) value); - } else if (value instanceof Number) { - // issue https://gitee.com/dromara/hutool/issues/I43U9G - // 避免float到double的精度问题 - if (value instanceof Float) { - cell.setCellValue(((Number) value).floatValue()); - } else { - cell.setCellValue(((Number) value).doubleValue()); - } - } else { - cell.setCellValue(value.toString()); - } + CellSetterFactory.createCellSetter(value).setValue(cell); } /** @@ -495,36 +454,5 @@ public class CellUtil { } return null; } - - /** - * 获取数字类型的单元格值 - * - * @param cell 单元格 - * @return 单元格值,可能为Long、Double、Date - */ - private static Object getNumericValue(Cell cell) { - final double value = cell.getNumericCellValue(); - - final CellStyle style = cell.getCellStyle(); - if (null != style) { - // 判断是否为日期 - if (ExcelDateUtil.isDateFormat(cell)) { - return DateUtil.date(cell.getDateCellValue());// 使用Hutool的DateTime包装 - } - - final String format = style.getDataFormatString(); - // 普通数字 - if (null != format && format.indexOf(StrUtil.C_DOT) < 0) { - final long longPart = (long) value; - if (((double) longPart) == value) { - // 对于无小数部分的数字类型,转为Long - return longPart; - } - } - } - - // 某些Excel单元格值为double计算结果,可能导致精度问题,通过转换解决精度问题。 - return Double.parseDouble(NumberToTextConverter.toText(value)); - } // -------------------------------------------------------------------------------------------------------------- Private method end } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellValue.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellValue.java index c23a470f5..228cc638b 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellValue.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellValue.java @@ -2,15 +2,16 @@ package cn.hutool.poi.excel.cell; /** * 抽象的单元格值接口,用于判断不同类型的单元格值 - * + * * @param 值得类型 * @author looly * @since 4.0.11 */ public interface CellValue { + /** * 获取单元格值 - * + * * @return 值 */ T getValue(); diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java index 70f9dd0a3..db3104681 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/FormulaCellValue.java @@ -1,12 +1,19 @@ package cn.hutool.poi.excel.cell; +import org.apache.poi.ss.usermodel.Cell; + /** - * 公式类型的值 + * 公式类型的值
+ * + * * * @author looly * @since 4.0.11 */ -public class FormulaCellValue implements CellValue { +public class FormulaCellValue implements CellValue, CellSetter { /** * 公式 @@ -42,6 +49,11 @@ public class FormulaCellValue implements CellValue { return this.formula; } + @Override + public void setValue(Cell cell) { + cell.setCellFormula(this.formula); + } + /** * 获取结果 * @return 结果 diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/BooleanCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/BooleanCellSetter.java new file mode 100755 index 000000000..1ccc29678 --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/BooleanCellSetter.java @@ -0,0 +1,29 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; + +/** + * {@link Boolean} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class BooleanCellSetter implements CellSetter { + + private final Boolean value; + + /** + * 构造 + * + * @param value 值 + */ + BooleanCellSetter(Boolean value) { + this.value = value; + } + + @Override + public void setValue(Cell cell) { + cell.setCellValue(value); + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CalendarCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CalendarCellSetter.java new file mode 100755 index 000000000..0e7050dd5 --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CalendarCellSetter.java @@ -0,0 +1,31 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; + +import java.util.Calendar; + +/** + * {@link Calendar} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class CalendarCellSetter implements CellSetter { + + private final Calendar value; + + /** + * 构造 + * + * @param value 值 + */ + CalendarCellSetter(Calendar value) { + this.value = value; + } + + @Override + public void setValue(Cell cell) { + cell.setCellValue(value); + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CellSetterFactory.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CellSetterFactory.java new file mode 100755 index 000000000..2cb38edae --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CellSetterFactory.java @@ -0,0 +1,45 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.RichTextString; + +import java.time.temporal.TemporalAccessor; +import java.util.Calendar; +import java.util.Date; + +/** + * {@link CellSetter} 简单静态工厂类,用于根据值类型创建对应的{@link CellSetter} + * + * @author looly + * @since 5.7.8 + */ +public class CellSetterFactory { + + /** + * 创建值对应类型的{@link CellSetter} + * + * @param value 值 + * @return {@link CellSetter} + */ + public static CellSetter createCellSetter(Object value) { + if (null == value) { + return NullCellSetter.INSTANCE; + } else if (value instanceof CellSetter) { + return (CellSetter) value; + } else if (value instanceof Date) { + return new DateCellSetter((Date) value); + } else if (value instanceof TemporalAccessor) { + return new TemporalAccessorCellSetter((TemporalAccessor) value); + } else if (value instanceof Calendar) { + return new CalendarCellSetter((Calendar) value); + } else if (value instanceof Boolean) { + return new BooleanCellSetter((Boolean) value); + } else if (value instanceof RichTextString) { + return new RichTextCellSetter((RichTextString) value); + } else if (value instanceof Number) { + return new NumberCellSetter((Number) value); + } else { + return new CharSequenceCellSetter(value.toString()); + } + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CharSequenceCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CharSequenceCellSetter.java new file mode 100755 index 000000000..58ae6e0ae --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/CharSequenceCellSetter.java @@ -0,0 +1,29 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; + +/** + * {@link CharSequence} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class CharSequenceCellSetter implements CellSetter { + + private final CharSequence value; + + /** + * 构造 + * + * @param value 值 + */ + CharSequenceCellSetter(CharSequence value) { + this.value = value; + } + + @Override + public void setValue(Cell cell) { + cell.setCellValue(value.toString()); + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/DateCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/DateCellSetter.java new file mode 100755 index 000000000..5e201bd9d --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/DateCellSetter.java @@ -0,0 +1,31 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; + +import java.util.Date; + +/** + * {@link Date} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class DateCellSetter implements CellSetter { + + private final Date value; + + /** + * 构造 + * + * @param value 值 + */ + DateCellSetter(Date value) { + this.value = value; + } + + @Override + public void setValue(Cell cell) { + cell.setCellValue(value); + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/NullCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/NullCellSetter.java new file mode 100755 index 000000000..182fbc78f --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/NullCellSetter.java @@ -0,0 +1,21 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; + +/** + * {@link Number} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class NullCellSetter implements CellSetter { + + public static final NullCellSetter INSTANCE = new NullCellSetter(); + + @Override + public void setValue(Cell cell) { + cell.setCellValue(StrUtil.EMPTY); + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/NumberCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/NumberCellSetter.java new file mode 100755 index 000000000..5f98f8e79 --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/NumberCellSetter.java @@ -0,0 +1,35 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; + +/** + * {@link Number} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class NumberCellSetter implements CellSetter { + + private final Number value; + + /** + * 构造 + * + * @param value 值 + */ + NumberCellSetter(Number value) { + this.value = value; + } + + @Override + public void setValue(Cell cell) { + // issue https://gitee.com/dromara/hutool/issues/I43U9G + // 避免float到double的精度问题 + if (value instanceof Float) { + cell.setCellValue(value.floatValue()); + } else { + cell.setCellValue(value.doubleValue()); + } + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/RichTextCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/RichTextCellSetter.java new file mode 100755 index 000000000..25ac0f44c --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/RichTextCellSetter.java @@ -0,0 +1,30 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.RichTextString; + +/** + * {@link RichTextString} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class RichTextCellSetter implements CellSetter { + + private final RichTextString value; + + /** + * 构造 + * + * @param value 值 + */ + RichTextCellSetter(RichTextString value) { + this.value = value; + } + + @Override + public void setValue(Cell cell) { + cell.setCellValue(value); + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/TemporalAccessorCellSetter.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/TemporalAccessorCellSetter.java new file mode 100755 index 000000000..a6d99d8f1 --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/setters/TemporalAccessorCellSetter.java @@ -0,0 +1,41 @@ +package cn.hutool.poi.excel.cell.setters; + +import cn.hutool.poi.excel.cell.CellSetter; +import org.apache.poi.ss.usermodel.Cell; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.TemporalAccessor; +import java.util.Date; + +/** + * {@link TemporalAccessor} 值单元格设置器 + * + * @author looly + * @since 5.7.8 + */ +public class TemporalAccessorCellSetter implements CellSetter { + + private final TemporalAccessor value; + + /** + * 构造 + * + * @param value 值 + */ + TemporalAccessorCellSetter(TemporalAccessor value) { + this.value = value; + } + + @Override + public void setValue(Cell cell) { + if (value instanceof Instant) { + cell.setCellValue(Date.from((Instant) value)); + } else if (value instanceof LocalDateTime) { + cell.setCellValue((LocalDateTime) value); + } else if (value instanceof LocalDate) { + cell.setCellValue((LocalDate) value); + } + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/ErrorCellValue.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/ErrorCellValue.java new file mode 100755 index 000000000..b4bd570df --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/ErrorCellValue.java @@ -0,0 +1,32 @@ +package cn.hutool.poi.excel.cell.values; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.cell.CellValue; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.FormulaError; + +/** + * ERROR类型单元格值 + * + * @author looly + * @since 5.7.8 + */ +public class ErrorCellValue implements CellValue { + + private final Cell cell; + + /** + * 构造 + * + * @param cell {@link Cell} + */ + public ErrorCellValue(Cell cell){ + this.cell = cell; + } + + @Override + public String getValue() { + final FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); + return (null == error) ? StrUtil.EMPTY : error.getString(); + } +} diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/NumericCellValue.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/NumericCellValue.java new file mode 100755 index 000000000..951af97c2 --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/values/NumericCellValue.java @@ -0,0 +1,57 @@ +package cn.hutool.poi.excel.cell.values; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.ExcelDateUtil; +import cn.hutool.poi.excel.cell.CellValue; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.util.NumberToTextConverter; + +/** + * 数字类型单元格值
+ * 单元格值可能为Long、Double、Date + * + * @author looly + * @since 5.7.8 + */ +public class NumericCellValue implements CellValue { + + private final Cell cell; + + /** + * 构造 + * + * @param cell {@link Cell} + */ + public NumericCellValue(Cell cell){ + this.cell = cell; + } + + @Override + public Object getValue() { + final double value = cell.getNumericCellValue(); + + final CellStyle style = cell.getCellStyle(); + if (null != style) { + // 判断是否为日期 + if (ExcelDateUtil.isDateFormat(cell)) { + // 使用Hutool的DateTime包装 + return DateUtil.date(cell.getDateCellValue()); + } + + final String format = style.getDataFormatString(); + // 普通数字 + if (null != format && format.indexOf(StrUtil.C_DOT) < 0) { + final long longPart = (long) value; + if (((double) longPart) == value) { + // 对于无小数部分的数字类型,转为Long + return longPart; + } + } + } + + // 某些Excel单元格值为double计算结果,可能导致精度问题,通过转换解决精度问题。 + return Double.parseDouble(NumberToTextConverter.toText(value)); + } +}