起因

目前项目中需要使用easyExcel 读取Excel文件,因为后端使用mongodb存储格式,数据格式不确定。因此读取文件时,未传递.class对象(指用方法一调用),使用String 接收Number 类型时,出现 .0情况。

本文依赖

 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.0.0-beta6</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></exclusion><exclusion><groupId>log4j</groupId><artifactId>log4j</artifactId></exclusion></exclusions></dependency>

官方文档分析

easyExcel 官方文档描述如下, 如果传递了 .class 对象接收,则可以使用官方的NumberFormat.format()方式处理。
如果没有传递 接受对象那该如何处理呢?

源代码分析

easyExcel 都是通过各种 转换器(Converter) 实现的,因此我们可以找到对应 StringNumberConverter 转换器,其源代码如下:


/*** String and number converter** @author Jiaju Zhuang*/
public class StringNumberConverter implements Converter<String> {@Overridepublic Class supportJavaTypeKey() {return String.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.NUMBER;}@Overridepublic String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {// 如果传递了 .class 接收,则 contentProperty 不为空// If there are "DateTimeFormat", read as date, // 获取 contentProperty  对象上是否有加日期格式注解if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {return DateUtils.format(HSSFDateUtil.getJavaDate(cellData.getDoubleValue(),contentProperty.getDateTimeFormatProperty().getUse1904windowing(), null),contentProperty.getDateTimeFormatProperty().getFormat());}// If there are "NumberFormat", read as number// 获取 contentProperty  对象上是否有加数字格式注解if (contentProperty != null && contentProperty.getNumberFormatProperty() != null) {return NumberUtils.format(cellData.getDoubleValue(), contentProperty);}// Excel defines formatting// 如果没有格式注解// 注意: 如果 Excel 为Number 类型,则 cellData.getDataFormat() = 0!!!if (cellData.getDataFormat() != null) {// 判断是否为日期格式if (DateUtil.isADateFormat(cellData.getDataFormat(), cellData.getDataFormatString())) {return DateUtils.format(HSSFDateUtil.getJavaDate(cellData.getDoubleValue(),globalConfiguration.getUse1904windowing(), null));} else {// 如果不是日期格式就直接调用这个方法, 该方法会 保留 .0的情况。可以进行拓展return NumberUtils.format(cellData.getDoubleValue(), contentProperty);}}// Default conversion numberreturn NumberUtils.format(cellData.getDoubleValue(), contentProperty);}@Overridepublic CellData convertToExcelData(String value, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {return new CellData(Double.valueOf(value));}
}

解决方案

自定义转换器,使用时再注册进去

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.DateUtils;
import com.alibaba.excel.util.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.util.NumberToTextConverter;import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.regex.Pattern;/*** todo:** @author : zhoulin.zhu* @date : 2020/4/28 10:17*/
public class CustomStringNumberConverter implements Converter<String> {@Overridepublic Class supportJavaTypeKey() {return String.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.NUMBER;}@Overridepublic String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {// If there are "DateTimeFormat", read as dateif (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {return com.alibaba.excel.util.DateUtils.format(HSSFDateUtil.getJavaDate(cellData.getDoubleValue(),contentProperty.getDateTimeFormatProperty().getUse1904windowing(), null),contentProperty.getDateTimeFormatProperty().getFormat());}// If there are "NumberFormat", read as numberif (contentProperty != null && contentProperty.getNumberFormatProperty() != null) {return NumberUtils.format(cellData.getDoubleValue(), contentProperty);}// Excel defines formattingif (cellData.getDataFormat() != null) {if (DateUtil.isADateFormat(cellData.getDataFormat(), cellData.getDataFormatString())) {if(cellData.getDataFormatString().contains(":")){return DateUtils.format(HSSFDateUtil.getJavaDate(cellData.getDoubleValue(),globalConfiguration.getUse1904windowing(), null));} else {return DateUtils.format(HSSFDateUtil.getJavaDate(cellData.getDoubleValue(),globalConfiguration.getUse1904windowing(), null), "yyyy-MM-dd");}}  else if(contentProperty == null) {try{// 百分比if(cellData.getDataFormatString() != null && cellData.getDataFormatString().contains("%")){return  new BigDecimal(cellData.getDoubleValue().toString()).multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString()  + "%";} else if(cellData.getDataFormatString() != null && cellData.getDataFormatString().equals("General")){//解决easyExcel 解析无 CLASS 对象时,Number to string  用String去接收数字,出现小数点等情况  方法一 会出现 数字位数失真的情况 ,即 excel 用公式计算数值后,只保留3位小数, 读取时 可能出现 直接去取保留前的N为小数的情况 建议使用方法二
//                     方法一   NumberFormat numberFormat = NumberFormat.getInstance();
//                        numberFormat.setMaximumFractionDigits(20);
//                        numberFormat.setGroupingUsed(false);//  return numberFormat.format(cellData.getDoubleValue());// 方法二return   NumberToTextConverter.toText(cellData.getDoubleValue());} else {return   NumberToTextConverter.toText(cellData.getDoubleValue());// return cellData.getDoubleValue().toString();}} catch (Exception e) {// 建议 统一使用以下方法,可以解决数值格式问题 return   NumberToTextConverter.toText(cellData.getDoubleValue());//   return NumberUtils.format(cellData.getDoubleValue(), contentProperty);}} else {return   NumberToTextConverter.toText(cellData.getDoubleValue());//  return NumberUtils.format(cellData.getDoubleValue(), contentProperty);}}// Default conversion number
//        NumberFormat numberFormat = NumberFormat.getInstance();
//        numberFormat.setMaximumFractionDigits(20);
//        numberFormat.setGroupingUsed(false);
//        return numberFormat.format(cellData.getDoubleValue());// 方法二return   NumberToTextConverter.toText(cellData.getDoubleValue());// return NumberUtils.format(cellData.getDoubleValue(), contentProperty);}@Overridepublic CellData convertToExcelData(String value, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {return new CellData(Double.valueOf(value));}
}

使用方法

   InputStream inputStream = file.getInputStream();// 可以是自己的监听器SalaryExcelListener excelListener = new SalaryExcelListener();EasyExcel.read(inputStream, excelListener).registerConverter(new CustomStringNumberConverter()).sheet().doRead();

使用效果对比

excel 数据:

使用前
{0=202003.0, 1=11.0, 2=XX, 3=2000.0, 4=1000, 5=7.5}
{0=202003.0, 1=90.0, 2=XX, 3=2000.0, 4=1000.0, 5=7.5}

使用后
{0=202003, 1=632511, 2=XX, 3=2000, 4=1000, 5=7.5}
{0=202003, 1=624190, 2=XX, 3=2000, 4=1000, 5=7.5}

解决easyExcel读取EXCEL用String去接收数字,出现小数点BUG相关推荐

  1. EasyExcel读取Excel日期为数字如何解决

    问题: 使用 EasyExcel 读取 Excel 数据时,表格中的日期自动转化为了一串数字 原因: 因为 Excel 导入的时间是以1900 年为原点的,而数字 34839 和 36577 则是19 ...

  2. Easyexcel·读取excel

    Easyexcel·读取excel 依赖 数据表 表的实体类 接口 表的crud操作 此接口用于将excel数据写入mysql测试表表中 测试数据导写入到excle中与读取excel数据 读取exce ...

  3. Java 使用EasyExcel读取Excel中多个sheet方法及示例代码

    本文主要介绍Java中,使用EasyExcel读取Excel文件中多个Sheet的方法,以及使用示例代码. 1.读取数据的实体对象 @Data public class DemoData {priva ...

  4. 使用 EasyExcel 读取Excel 解析复杂表格

    使用 EasyExcel 读取Excel 解析复杂表格 解析如下复杂表格(比这个更复杂的也可以) 引入依赖 创建实体类 继承 需要继承 (BaseRowModel) 同步读取 ( 数据量大的时候,不推 ...

  5. 快速使用EasyExcel读取Excel

    快速使用EasyExcel读取Excel EasyExcel使用过程 创建接口 OrderUploadExcelListener 类 EasyExcel使用过程 首先导入Maven依赖 创建接口 Ea ...

  6. python excel写入日期变数字_解决python 读取excel时 日期变成数字并加.0的问题

    excel 文件内容如下: 读取excel内容: import xlrd from datetime import datetime from xlrd import xldate_as_dateti ...

  7. 阿里的Easyexcel读取Excel文件(最新版本)

      本篇文章主要介绍一下使用阿里开源的Easyexcel工具处理读取excel文件,因为之前自己想在网上找一下这个简单的立即上手的博客,发现很多文章的教程都针对比较旧的版本的Easyexcel,没有使 ...

  8. easyexcel 检查表头是否匹配_Java EasyExcel读取Excel表头数据的方法及示例代码

    1、读取表头数据代码/** * 读取表头数据 * * * 1. 创建excel对应的实体对象 参照{@link DemoData} * * 2. 由于默认异步读取excel,所以需要创建excel一行 ...

  9. easyexcel读取excel合并单元格数据

    普通的excel列表,easyexcel读取是没有什么问题的.但是,如果有合并单元格,那么它读取的时候,能获取数据,但是数据是不完整的.如下所示的单元格数据: 我们通过简单的异步读取,最后查看数据内容 ...

最新文章

  1. EF Core Model更新迁移
  2. WPF实现聚光灯效果
  3. Servlet之Tomcat配置与启动(一)
  4. 本机获取Intel AMT IP地址的例子
  5. Akka 配置Dispatcher(一)
  6. Gson 转化为带反斜杠的json
  7. java 面向对象基础
  8. Visual Studio Community 2017安装步骤(只装C++)
  9. 电脑蓝牙音箱,电脑怎么连蓝牙音响吗
  10. 自考《操作系统概论》
  11. docker安装konga系统
  12. 【Elasticsearch】bulk的使用
  13. LeetCode刷题 876链表的中间结点
  14. 问渠哪得清如许,唯有源头活水来-浅谈android 系统
  15. idea如何配置Mybatis简单易懂
  16. 生物-大脑极限:大脑极限
  17. ARM Cortex-A77架构解读
  18. 滑坡泥石流的防御措施_滑坡泥石流防范措施
  19. 大神f2刷机后卡在android,酷派大神F2 8675-A系统运行速度变慢变卡顿_怎么刷机来解决...
  20. Dell U2414H 输入连接类型

热门文章

  1. 计算机丢失slimage.dll,slimage.dll
  2. 【Jmeter】安装配置:Jmeter 自定义创建桌面快捷方式
  3. 《JavaScript设计模式》读后感 觉很复杂
  4. Android ViewPager Fragment 切换刷新数据,解决生命周期只走一次的问题
  5. Kafka 3.0 源码笔记(3)-Kafka 消费者的核心流程源码分析
  6. spark踩坑记录 (一) group by
  7. python renamer模块_python - 发布自己的模块(脚本) 到pypi.org
  8. 大数据股票接口怎么获取比较全面的股票信息?
  9. 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(9)链表
  10. 电脑安装win8.1后 前面板没有声音的解决办法