hutool读取excel 数字类型精度丢失问题解决

ExcelReader reader = ExcelUtil.getReader(iStream);

设置自定义的类型转换器, 默认的类型转换器在数值型的转换时double强转为long会造成精度的丢失

 reader.setCellEditor(new NumberToString());



/** * @Title NumberToString.java* @Package com.baozun.ecs.oms4.dms.manager.diff.ikea* @Description: TODO(用一句话描述该文件做什么)* @author zsh11619* @date 2020年6月17日* @version V1.0 */ package com.baozun.ecs.oms4.dms.manager.diff.ikea;import java.util.List;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.CellStyle;import org.apache.poi.ss.usermodel.CellType;import org.apache.poi.ss.usermodel.FormulaError;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.util.CellRangeAddress;import org.apache.poi.ss.util.NumberToTextConverter;import org.apache.poi.ss.util.SheetUtil;import cn.hutool.core.date.DateUtil;import cn.hutool.core.util.StrUtil;import cn.hutool.poi.excel.cell.CellEditor;/*** @ClassName NumberToString* @Package com.baozun.ecs.oms4.dms.manager.diff.ikea* @Description 数值类型精度丢失问题处理* @author zsh11619* @date 2020年6月17日**/public class NumberToString implements CellEditor { @Override public Object edit(Cell cell, Object value) { if (null == cell) { return null; } CellType cellType = cell.getCellTypeEnum(); if(CellType.BLANK == cellType){ // 空白单元格可能为合并单元格 cell = getMergedRegionCell(cell); cellType = cell.getCellTypeEnum(); } switch (cellType) { case NUMERIC: value = getNumericValue(cell); break; case BOOLEAN: value = cell.getBooleanCellValue(); break; case FORMULA: // 遇到公式时查找公式结果类型 break; case BLANK: value = StrUtil.EMPTY; break; case ERROR: final FormulaError error = FormulaError.forInt(cell.getErrorCellValue()); value = (null == error) ? StrUtil.EMPTY : error.getString(); break; default: value = cell.getStringCellValue(); } return value; } private Object getNumericValue(Cell cell) { final double value = cell.getNumericCellValue(); final CellStyle style = cell.getCellStyle(); if (null != style) { final short formatIndex = style.getDataFormat(); // 判断是否为日期 if (isDateType(cell, formatIndex)) { return DateUtil.date(cell.getDateCellValue());// 使用Hutool的DateTime包装 } final String format = style.getDataFormatString(); // 普通数字 if (null != format && format.indexOf(StrUtil.C_DOT) < 0) { return NumberToTextConverter.toText(value); } } // 某些Excel单元格值为double计算结果,可能导致精度问题,通过转换解决精度问题。 return Double.parseDouble(NumberToTextConverter.toText(value)); } /** * 是否为日期格式

* 判断方式:    *    *

    * 1、指定序号

    * 2、org.apache.poi.ss.usermodel.DateUtil.isADateFormat方法判定

    *

*    * @param cell        单元格    * @param formatIndex 格式序号    * @return 是否为日期格式    */    private static boolean isDateType(Cell cell, int formatIndex) {        // yyyy-MM-dd----- 14        // yyyy年m月d日---- 31        // yyyy年m月------- 57        // m月d日 ---------- 58        // HH:mm----------- 20        // h时mm分 -------- 32        if (formatIndex == 14 || formatIndex == 31 || formatIndex == 57 || formatIndex == 58 || formatIndex == 20 || formatIndex == 32) {            return true;        }        return org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell);    }        /**    * 获取合并单元格

* 传入的x,y坐标(列行数)可以是合并单元格范围内的任意一个单元格    *    * @param cell {@link Cell}    * @return 合并单元格    * @since 5.1.5    */    public static Cell getMergedRegionCell(Cell cell) {        return getMergedRegionCell(cell.getSheet(), cell.getColumnIndex(), cell.getRowIndex());    }        public static Cell getMergedRegionCell(Sheet sheet, int x, int y) {        final List addrs = sheet.getMergedRegions(); int firstColumn; int lastColumn; int firstRow; int lastRow; for (CellRangeAddress ca : addrs) { firstColumn = ca.getFirstColumn(); lastColumn = ca.getLastColumn(); firstRow = ca.getFirstRow(); lastRow = ca.getLastRow(); if (y >= firstRow && y <= lastRow) { if (x >= firstColumn && x <= lastColumn) { return SheetUtil.getCell(sheet, firstRow, firstColumn); } } } return SheetUtil.getCell(sheet, y, x); } }

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容