Spring Boot POI中BigDecimal类型数据写入Excel单元格

正确做法

应该将 BigDecimal 转换为 POI 单元格支持的合适类型,例如 double 或 String

方案一:转换为 double(推荐,适合数值计算)

java

if (capitalInfoVO.getCapitalTotal() != null) {
    row.createCell(4).setCellValue(capitalInfoVO.getCapitalTotal().doubleValue());
}

注意double 可能丢失精度(特别是大数值或高精度小数),但通常金额类数据使用 double 足够。若需保留原样,可使用方案二。

方案二:转换为字符串(保留原格式)

java

if (capitalInfoVO.getCapitalTotal() != null) {
    row.createCell(4).setCellValue(capitalInfoVO.getCapitalTotal().toString());
}

此时 Excel 单元格会以文本形式存储,可能影响后续计算。

方案三:设置数字格式(最佳实践)

如果需要精确数值并保留格式,可以创建带有数字格式的 CellStyle

java

// 创建数字格式样式
CellStyle numberStyle = workbook.createCellStyle();
numberStyle.setDataFormat(workbook.createDataFormat().getFormat("#,##0.00")); // 根据需求调整

if (capitalInfoVO.getCapitalTotal() != null) {
    Cell cell = row.createCell(4);
    cell.setCellValue(capitalInfoVO.getCapitalTotal().doubleValue());
    cell.setCellStyle(numberStyle);
}

修正后的完整片段

java

// 浮点数类型(BigDecimal类型)
if (capitalInfoVO.getCapitalTotal() != null) {
    row.createCell(4).setCellValue(capitalInfoVO.getCapitalTotal().doubleValue());
}
if (capitalInfoVO.getCapitalLeaveTotal() != null) {
    row.createCell(5).setCellValue(capitalInfoVO.getCapitalLeaveTotal().doubleValue());
}
if (capitalInfoVO.getCapitalValidTotal() != null) {
    row.createCell(6).setCellValue(capitalInfoVO.getCapitalValidTotal().doubleValue());
}

或者,如果希望保留精确字符串表示:

java

row.createCell(4).setCellValue(capitalInfoVO.getCapitalTotal().toString());

完整示例代码:

示例1:手动关闭资源

    /**
     * 导出数据文件
     */
    public String exportFile(CapitalInfoQueryDTO queryDTO) {
        // 获取资金信息列表
        List<CapitalInfoVO> capitalInfoVOs;
        if (isAllQueryParamsEmpty(queryDTO)) {
            capitalInfoVOs = refreshList();
        } else {
            capitalInfoVOs = queryList(queryDTO);
        }

        try {
            // 1、创建工作薄(excel文件,.xlsx文件)
            XSSFWorkbook workbook = new XSSFWorkbook();
            // 2、创建工作表
            XSSFSheet sheet = workbook.createSheet("资金信息");

            // 3、创建工作表表头
            XSSFRow headerRow = sheet.createRow(0);
            headerRow.createCell(0).setCellValue("创建时间");
            headerRow.createCell(1).setCellValue("资金序号");
            headerRow.createCell(2).setCellValue("资金名称");
            headerRow.createCell(3).setCellValue("资金类别");
            headerRow.createCell(4).setCellValue("指标预算总额");
            headerRow.createCell(5).setCellValue("指标剩余额");
            headerRow.createCell(6).setCellValue("指标可用总额");
            headerRow.createCell(7).setCellValue("指标类别");
            headerRow.createCell(8).setCellValue("资金账户");
            headerRow.createCell(9).setCellValue("资金来源");
            headerRow.createCell(10).setCellValue("指标来源");
            headerRow.createCell(11).setCellValue("资金年份");
            headerRow.createCell(12).setCellValue("状态");
            headerRow.createCell(13).setCellValue("备注信息");

            // 创建日期格式样式
            CellStyle dateCellStyle = workbook.createCellStyle();
            CreationHelper createHelper = workbook.getCreationHelper();
            dateCellStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));

            // 创建数字格式样式
            CellStyle numberCellStyle = workbook.createCellStyle();
            numberCellStyle.setDataFormat(workbook.createDataFormat().getFormat("#,##0.00"));

            // 4、填充数据
            int rowIndex = 1;
            for (CapitalInfoVO capitalInfoVO : capitalInfoVOs) {
                Row row = sheet.createRow(rowIndex++);

                // 日期类型:创建时间
                if (capitalInfoVO.getCreateTime() != null) {
                    Cell cell = row.createCell(0);
                    cell.setCellValue(capitalInfoVO.getCreateTime());
                    // 设置日期样式
                    cell.setCellStyle(dateCellStyle);
                }

                // 字符串类型
                row.createCell(1).setCellValue(capitalInfoVO.getCapitalNo());
                row.createCell(2).setCellValue(capitalInfoVO.getCapitalName());
                row.createCell(3).setCellValue(capitalInfoVO.getCapitalType());
                row.createCell(7).setCellValue(capitalInfoVO.getCapitalIndexType());
                row.createCell(8).setCellValue(capitalInfoVO.getCapitalAccount());
                row.createCell(9).setCellValue(capitalInfoVO.getCapitalSource());
                row.createCell(10).setCellValue(capitalInfoVO.getCapitalIndexSource());
                row.createCell(13).setCellValue(capitalInfoVO.getRemark());

                // 浮点数类型(BigDecimal类型),处理 null 值
                if (capitalInfoVO.getCapitalTotal() != null) {
                    // 方案一:转换为 double(推荐,适合数值计算)
                    row.createCell(4).setCellValue(capitalInfoVO.getCapitalTotal().doubleValue());
                }
                if (capitalInfoVO.getCapitalLeaveTotal() != null) {
                    // 方案二:转换为字符串(保留原格式)
                    row.createCell(5).setCellValue(capitalInfoVO.getCapitalLeaveTotal().toString());
                }
                if (capitalInfoVO.getCapitalValidTotal() != null) {
                    // 方案三:设置数字格式(最佳实践)
                    Cell cell = row.createCell(6);
                    cell.setCellValue(capitalInfoVO.getCapitalValidTotal().doubleValue());
                    // 设置数字样式
                    cell.setCellStyle(numberCellStyle);
                }

                // 整数类型(Integer类型),处理 null 值
                if (capitalInfoVO.getCapitalYear() != null) {
                    row.createCell(11).setCellValue(capitalInfoVO.getCapitalYear());
                }
                if (capitalInfoVO.getCapitalState() != null) {
                    String value = switch (capitalInfoVO.getCapitalState()) {
                        case 0 -> CapitalInfoStateEnum.IN_USE.getDescription();
                        case 1 -> CapitalInfoStateEnum.RETURNED.getDescription();
                        case 2 -> CapitalInfoStateEnum.CLOSED.getDescription();
                        default -> "";
                    };
                    row.createCell(12).setCellValue(value);
                }
            }

            // 5、生成excel文件
            // 使用当前时间戳使文件名唯一
            String timestamp = String.valueOf(System.currentTimeMillis());
            String filename = "资金信息-" + timestamp + ".xlsx";
            String filePath = fileSaveUtils.getAppDirectory() + filename;
            FileOutputStream fileOut = new FileOutputStream(filePath);
            workbook.write(fileOut);

            // 关闭文件输出流,释放资源
            fileOut.close();
            // 关闭workbook对象,释放资源
            workbook.close();

            // 6、返回文件绝对路径
            return filePath;

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

示例2:使用 try-with-resources 自动关闭 资源

    /**
     * 导出数据
     */
    public String exportFile(CapitalInfoQueryDTO queryDTO) {
        // 获取资金信息列表
        List<CapitalInfoVO> capitalInfoVOs;
        if (isAllQueryParamsEmpty(queryDTO)) {
            capitalInfoVOs = refreshList();
        } else {
            capitalInfoVOs = queryList(queryDTO);
        }

        // 生成文件名和路径(不会抛出 IOException,提前构造)
        String timestamp = String.valueOf(System.currentTimeMillis());
        String filename = "资金信息-" + timestamp + ".xlsx";
        String filePath = fileSaveUtils.getAppDirectory() + filename;

        // 使用 try-with-resources 自动关闭 workbook 和 fileOut
        try (
                // 1、创建资源
                // 创建工作薄(excel文件,.xlsx文件)
                XSSFWorkbook workbook = new XSSFWorkbook();
                // 创建文件输出流
                FileOutputStream fileOut = new FileOutputStream(filePath)
        ) {
            // 2、创建工作表
            XSSFSheet sheet = workbook.createSheet("资金信息");

            // 3、创建工作表表头
            XSSFRow headerRow = sheet.createRow(0);
            headerRow.createCell(0).setCellValue("创建时间");
            headerRow.createCell(1).setCellValue("资金序号");
            headerRow.createCell(2).setCellValue("资金名称");
            headerRow.createCell(3).setCellValue("资金类别");
            headerRow.createCell(4).setCellValue("指标预算总额");
            headerRow.createCell(5).setCellValue("指标剩余额");
            headerRow.createCell(6).setCellValue("指标可用总额");
            headerRow.createCell(7).setCellValue("指标类别");
            headerRow.createCell(8).setCellValue("资金账户");
            headerRow.createCell(9).setCellValue("资金来源");
            headerRow.createCell(10).setCellValue("指标来源");
            headerRow.createCell(11).setCellValue("资金年份");
            headerRow.createCell(12).setCellValue("状态");
            headerRow.createCell(13).setCellValue("备注信息");

            // 创建日期格式样式
            CellStyle dateCellStyle = workbook.createCellStyle();
            CreationHelper createHelper = workbook.getCreationHelper();
            dateCellStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));

            // 创建数字格式样式
            CellStyle numberCellStyle = workbook.createCellStyle();
            numberCellStyle.setDataFormat(workbook.createDataFormat().getFormat("#,##0.00"));

            // 4、填充数据
            int rowIndex = 1;
            for (CapitalInfoVO capitalInfoVO : capitalInfoVOs) {
                Row row = sheet.createRow(rowIndex++);

                // 日期类型:创建时间
                if (capitalInfoVO.getCreateTime() != null) {
                    Cell cell = row.createCell(0);
                    cell.setCellValue(capitalInfoVO.getCreateTime());
                    // 设置日期样式
                    cell.setCellStyle(dateCellStyle);
                }

                // 字符串类型
                row.createCell(1).setCellValue(capitalInfoVO.getCapitalNo());
                row.createCell(2).setCellValue(capitalInfoVO.getCapitalName());
                row.createCell(3).setCellValue(capitalInfoVO.getCapitalType());
                row.createCell(7).setCellValue(capitalInfoVO.getCapitalIndexType());
                row.createCell(8).setCellValue(capitalInfoVO.getCapitalAccount());
                row.createCell(9).setCellValue(capitalInfoVO.getCapitalSource());
                row.createCell(10).setCellValue(capitalInfoVO.getCapitalIndexSource());
                row.createCell(13).setCellValue(capitalInfoVO.getRemark());

                // 浮点数类型(BigDecimal 类型),处理 null 值
                if (capitalInfoVO.getCapitalTotal() != null) {
                    // 方案一:转换为 double(推荐,适合数值计算)
                    row.createCell(4).setCellValue(capitalInfoVO.getCapitalTotal().doubleValue());
                }
                if (capitalInfoVO.getCapitalLeaveTotal() != null) {
                    // 方案二:转换为字符串(保留原格式)
                    row.createCell(5).setCellValue(capitalInfoVO.getCapitalLeaveTotal().toString());
                }
                if (capitalInfoVO.getCapitalValidTotal() != null) {
                    // 方案三:设置数字格式(最佳实践)
                    Cell cell = row.createCell(6);
                    cell.setCellValue(capitalInfoVO.getCapitalValidTotal().doubleValue());
                    // 设置数字样式
                    cell.setCellStyle(numberCellStyle);
                }

                // 整数类型(Integer 类型),处理 null 值
                if (capitalInfoVO.getCapitalYear() != null) {
                    row.createCell(11).setCellValue(capitalInfoVO.getCapitalYear());
                }
                if (capitalInfoVO.getCapitalState() != null) {
                    String value = switch (capitalInfoVO.getCapitalState()) {
                        case 0 -> CapitalInfoStateEnum.IN_USE.getDescription();
                        case 1 -> CapitalInfoStateEnum.RETURNED.getDescription();
                        case 2 -> CapitalInfoStateEnum.CLOSED.getDescription();
                        default -> "";
                    };
                    row.createCell(12).setCellValue(value);
                }
            }

            // 5、写入文件
            workbook.write(fileOut);

            // 6、返回文件绝对路径
            return filePath;

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

导出Excel效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值