当前位置: 首页 > news >正文

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

背景

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

在这里插入图片描述

分析原因

先看导出用到了什么工具 查看源码发现 导出 使用了 EasyExcel
在这里插入图片描述

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

去找导出实体对象 查看相应字段类型
在这里插入图片描述
很遗憾 并不是想象中的一般情况
这里的字段类型都是BigDecimal 按道理来说 导出的 数字 应该就是数字类型的

深入看了下代码 发现excel写入的过程涉及到不同列的权限显示问题 一些数据是 动态写入的 不是EasyExcel的简单通过对象导出
考虑到使用到的EasyExcel版本比较老 且需要设置 千分位 保留两位小数等 格式
在这里插入图片描述
就不再研究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

相关文章:

  • 动漫人物眼睛画法
  • win10电脑性能优化设置
  • 【ArcGIS Pro二次开发】(5):UI管理_自定义控件的位置
  • Jackson 序列化:Cannot deserialize value of type `java.time.LocalDateTime`
  • 自抗扰控制ADRC之微分器TD
  • Python 自己简单地造一个轮子.whl文件
  • C# 数据结构
  • 数据分析| Pandas200道练习题,使用Pandas连接MySQL数据库
  • 【函数栈帧的创建和销毁】 -- 神仙级别底层原理,你学会了吗?
  • Generated columns cannot be used in COPY
  • 2023年美赛C题 预测Wordle结果Predicting Wordle Results这题太简单了吧
  • 测试开发之Django实战示例 第十二章 创建API
  • Python 之 Matplotlib xticks 的再次说明、图形样式和子图
  • 2023美赛F题:绿色经济
  • 基于蜣螂算法改进的LSTM分类算法-附代码
  • 数字化系统使用率低的原因剖析
  • 【python百炼成魔】python之列表详解
  • ChatGPT国内镜像站初体验:聊天、Python代码生成等
  • K8s常见面试题总结
  • [TPAMI‘21] Heatmap Regression via Randomized Rounding
  • 成都一医院孕妇产下七胞胎?涉事医院辟谣:信息不实已举报
  • 上海召开全市加强社会治安综合治理中心规范化建设工作推进会
  • 在没有穹顶的剧院,和春天的音乐会来一场约会
  • 美国开始从叙利亚撤出数百人,分析人士担忧“伊斯兰国”威胁再起
  • 讲座预告|把握可持续信息披露新机遇
  • 贵州省纪委原副书记、省监委原副主任张平一审被控受贿4772万余元