问题
java通过poi读取excel单元格的小数时会出错,分析后发现是因为会损失精度。
处理的代码
/**
* DataFormatter 直接new就行:DataFormatter df = new DataFormatter();
*/
private String getNumericCellValue(Cell cell, DataFormatter df) {
String valueStr = df.formatCellValue(cell);// 格式化后的数字,比如会保留后面的0
if (StringUtils.isNotBlank(valueStr)) {
CellStyle cellStyle = cell.getCellStyle();
if (cellStyle != null) {
String formatString = cellStyle.getDataFormatString();
if ("General".equals(formatString)) {// 常规,则直接返回格式化后的值
return valueStr;
} else {
// 如果不是常规,比较准确数字和格式化后的数字小数位数是否一致
String valueString = String.valueOf(cell.getNumericCellValue());// 准确的数字
if (!valueString.endsWith("0")) {// 如果不是以0结尾,就获取字符串,否则可能不准确
cell.setCellType(Cell.CELL_TYPE_STRING);
String valueStringStr = cell.getStringCellValue();// 准确的数字字符串
if (!valueString.equals(valueStringStr)) {
logger.warn("数字与字符串不一致:" + valueString + "," + valueStringStr);
valueString = valueStringStr;
}
}
int pointNumString = MathUtil.getDecimalPlace(valueString);// 准确数字的小数位数
int pointNumStr = MathUtil.getDecimalPlace(valueStr);// 格式化后数字的小数位数
// 如果一致,或者格式化后的数字小数位数比准确数字多,则直接返回格式化后的值
if (pointNumString <= pointNumStr) {
return valueStr;
} else {// 否则设置保留的小数位数
return new BigDecimal(valueString).setScale(pointNumStr, BigDecimal.ROUND_HALF_UP).toPlainString();
}
}
}
}
return valueStr;
}