背景

某公司导出的一个Excel 其中有三列数据 是数字 但是导出后 实际上格式为 数值形式的字符串
客户要求这三列的格式改为 数值格式 且千分位分隔 保留两位小数

POI处理Excel (xlsx格式) 设置单元格格式为数值 且千分位分隔 保留两位小数_excel

分析原因

先看导出用到了什么工具 查看源码发现 导出 使用了 EasyExcel

POI处理Excel (xlsx格式) 设置单元格格式为数值 且千分位分隔 保留两位小数_保留两位小数_02

立马想到 一般情况下导出实体的字段类型可能是String 才会导致 数字类型 在Excel中是 数值类型的字符串

去找导出实体对象 查看相应字段类型

POI处理Excel (xlsx格式) 设置单元格格式为数值 且千分位分隔 保留两位小数_ide_03


很遗憾 并不是想象中的一般情况

这里的字段类型都是BigDecimal 按道理来说 导出的 数字 应该就是数字类型的深入看了下代码 发现excel写入的过程涉及到不同列的权限显示问题 一些数据是 动态写入的 不是EasyExcel的简单通过对象导出

考虑到使用到的EasyExcel版本比较老 且需要设置 千分位 保留两位小数等 格式

POI处理Excel (xlsx格式) 设置单元格格式为数值 且千分位分隔 保留两位小数_字段类型_04


就不再研究1.1.2版本的EasyExcel 了 (如果有感兴趣的或者研究过 EasyExcel实现这种功能的朋友 还请在评论区讨论下)

确定解决方案

既然Excel已经生成好了 那么就在已经生成好的Excel上再次处理 使用POI (很显然这种方式很不友好 消耗内存 浪费更多的时间去重新遍历Excel 但是可以快速的解决目前遇到的问题)

在使用POI 进行处理的时候又遇到了一个坑

又遇到坑

如果直接获取对应cell之后 获取String类型的数字 然后转成double 再塞到cell里面 最后设置千分位 保留两位小数 会发现不生效

// 单元格样式
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));
cellStyle.setAlignment(HorizontalAlignment.LEFT); //水平居左

String cellValue13 = cellOrigin13.getStringCellValue();
if(StringUtils.isNotEmpty(cellValue13)){
double parseDouble = Double.parseDouble(cellValue13);
cellNew13.setCellStyle(cellStyle);
cellNew13.setCellValue(parseDouble);
}
@PostMapping(value = "/export")
@ApiOperation(value = "导出")
public void exportForDistributor(@ParamHide CustomerBilling customerBilling, @ParamHide HttpServletRequest request, @ParamHide HttpServletResponse response) {
customerBilling.setExportData(true);
String filePath = customerBillingService.exportData(customerBilling, CustomerBillingData.class);

// 处理Excel 格式开始
if (StringUtils.isNotEmpty(filePath)) {
XSSFWorkbook wb = returnWorkBookGivenFileHandle(filePath);
if (wb == null) {
log.error("returnWorkBookGivenFileHandle 方法获取的 XSSFWorkbook 对象wb 为空");
return;
}
// 获取工作表1
XSSFSheet sheet1 = wb.getSheet("1");

// 获取总行数
int rowNum = sheet1.getPhysicalNumberOfRows();

// 单元格样式
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));
cellStyle.setAlignment(HorizontalAlignment.LEFT); //水平居左

if(rowNum > 6){
// 此时才有数据
// 第七行开始 第 N O P列 开票金额 到款金额 本单余额 需要进行格式处理 13 14 15 注意处理空值
for (int i = 6; i < rowNum; i++) {
XSSFRow row = sheet1.getRow(i);
XSSFCell cellOrigin13 = row.getCell(13);
XSSFCell cellOrigin14 = row.getCell(14);
XSSFCell cellOrigin15 = row.getCell(15);

String cellValue13 = cellOrigin13.getStringCellValue();
if(StringUtils.isNotEmpty(cellValue13)){
double parseDouble = Double.parseDouble(cellValue13);
XSSFCell cellNew13 = row.createCell(13);
cellNew13.setCellStyle(cellStyle);
cellNew13.setCellValue(parseDouble);
}else {
// 如果为空则创建空的空格 格式也做相同处理
XSSFCell cellNew13 = row.createCell(13);
cellNew13.setCellStyle(cellStyle);
}

String cellValue14 = cellOrigin14.getStringCellValue();
if(StringUtils.isNotEmpty(cellValue14)){
double parseDouble = Double.parseDouble(cellValue14);
XSSFCell cellNew14 = row.createCell(14);
cellNew14.setCellStyle(cellStyle);
cellNew14.setCellValue(parseDouble);
}else {
// 如果为空则创建空的空格 格式也做相同处理
XSSFCell cellNew14 = row.createCell(14);
cellNew14.setCellStyle(cellStyle);
}

String cellValue15 = cellOrigin15.getStringCellValue();
if(StringUtils.isNotEmpty(cellValue15)){
double parseDouble = Double.parseDouble(cellValue15);
XSSFCell cellNew15 = row.createCell(15);
cellNew15.setCellStyle(cellStyle);
cellNew15.setCellValue(parseDouble);
}else {
// 如果为空则创建空的空格 格式也做相同处理
XSSFCell cellNew15 = row.createCell(15);
cellNew15.setCellStyle(cellStyle);
}
saveExcel(wb,filePath);
}
}
}
// 处理Excel 格式结束


CommonUtil.downloadJxlExcel(request, response, filePath, "客户对账单.xlsx");
}


/**
* 得到一个已有的工作薄的POI对象
*
* @return XSSFWorkbook 对象
*/
private XSSFWorkbook returnWorkBookGivenFileHandle(String filePath) {
XSSFWorkbook wb = null;
InputStream inputStream = null;
try {
File file = new File(filePath);
// 获得inputStream对象
try {
inputStream = new FileInputStream(file);
} catch (IOException e) {
log.error("获取模板输入流为空 e", e);
}
if (inputStream != null) {
wb = new XSSFWorkbook(inputStream);
}
} catch (Exception e) {
log.error("获取Excel文件出错", e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ignore) {
}
}
}
return wb;
}


/**
* 保存工作薄
*
* @param wb XSSFWorkbook对象
*/
private void saveExcel(XSSFWorkbook wb, String filePath) {
FileOutputStream fileOut;
try {
fileOut = new FileOutputStream(filePath);
wb.write(fileOut);
fileOut.close();
} catch (IOException e) {
log.error("保存工作薄出错 e", e);
}
}

重处理Excel