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;
+
/**
- * 公式类型的值
+ * 公式类型的值
+ *
+ *
+ * - 在Sax读取模式时,此对象用于接收单元格的公式以及公式结果值信息
+ * - 在写出模式时,用于定义写出的单元格类型为公式
+ *
*
* @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