【POI框架实战】——POI导出Excel时设置单元格类型为数值类型

【POI框架实战】——POI导出Excel时设置单元格类型为数值类型最近做的一个 ITFIN 的项目中 导出的数据中有文本格式 也有货币格式 所以为了方便在将来导出的表格中做计算 存放货币先用正则表达式判断数据是否为数值型 如果为数值型 则设置单元格格式为整数或者小数 然后往单元格中存放数据的时候要设置数据的格式为 double 类型 如果查看 poi 的源码 HSSFCell java 会发现设置数据的方法如下 所以用 setCellValue double 方法即可


  最近做的一个ITFIN的项目中,后台需要用POI实现导出功能,导出的数据中有文本格式,也有货币格式,所以为了方便在将来导出的表格中做计算,存放货币的单元格需要设置为数值类型。

  导出的Excel的单元格都是文本格式(单元格左上角有个小三角):

这里写图片描述

  费了不少功夫,终于把“小三角”去掉了,这里总结并分享一下问题的解决方法。

  通过poi导出excel的过程大致是这样的:






     规定单元格的格式
        ↓
      创建单元格
        ↓
     设置单元格的格式
        ↓
     设置数据的格式
        ↓
    把数据存放到单元格中
        ↓
      通过IO流输出



















背景POI导出Excel时设置单元格类型为数值类型


  要想存放数值的单元格以数值类型导出,其中最关键的步骤就是上面加粗的两步,设置单元格的格式和向单元格中存放数据。

  核心代码如下:

 / * 导出Excel-2015年11月11日 * *@param outPutParam Excel数据实体,包括要导出的excel标头、列标题、数据等 * */ private void createContentRows(ExcelParam outPutParam) { HSSFWorkbook workbook=new HSSFWorkbook(); //创建一个Excel文件 // 遍历集合数据,产生数据行 for (int i = 0; i < outPutParam.getContent().size(); i++) { int rowIndex = i + 2; HSSFRow contentRow = sheet.createRow(rowIndex); Map 
     
       rowDate = outPutParam.getContent().get(i); //遍历列 for (int j = 0; j < outPutParam.getTitleList().size(); j++) { Title headTitle = outPutParam.getTitleList().get(j);//获取第i行第j列列标题 String headerName = headTitle.getName();//获取第j列列标识 Object data = rowDate.get(headerName);//获取第i行第j列所放数据 HSSFCellStyle contextstyle =workbook.createCellStyle(); HSSFCell contentCell = contentRow.createCell(j); Boolean isNum = false;//data是否为数值型 Boolean isInteger=false;//data是否为整数 Boolean isPercent=false;//data是否为百分数 if (data != null || "".equals(data)) { //判断data是否为数值型 isNum = data.toString().matches("^(-?\\d+)(\\.\\d+)?$"); //判断data是否为整数(小数部分是否为0) isInteger=data.toString().matches("^[-\\+]?[\\d]*$"); //判断data是否为百分数(是否包含“%”) isPercent=data.toString().contains("%"); } //如果单元格内容是数值类型,涉及到金钱(金额、本、利),则设置cell的类型为数值型,设置data的类型为数值类型 if (isNum && !isPercent) { HSSFDataFormat df = workbook.createDataFormat(); // 此处设置数据格式 if (isInteger) { contextstyle.setDataFormat(df.getBuiltinFormat("#,#0"));//数据格式只显示整数 }else{ contextstyle.setDataFormat(df.getBuiltinFormat("#,0.00"));//保留两位小数点 } // 设置单元格格式 contentCell.setCellStyle(contextstyle); // 设置单元格内容为double类型 contentCell.setCellValue(Double.parseDouble(data.toString())); } else { contentCell.setCellStyle(contextstyle); // 设置单元格内容为字符型 contentCell.setCellValue(data.toString()); } } } } 
     

  如上,有两个比较重要的点:
  1、先用正则表达式判断数据是否为数值型,如果为数值型,则设置单元格格式为整数或者小数;
  2、然后往单元格中存放数据的时候要设置数据的格式为double类型,如果查看poi的源码HSSFCell.java会发现设置数据的方法如下,所以用setCellValue(double)方法即可。



这里写图片描述

优化


  到了这里,您可能以为万事大吉啊了,其实上面的代码有个陷阱,如果不经过大数据量的测试是发觉不出来的哦~~

  如果数据量大的话,系统可能会报错“The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook”,原因是style创建的次数太多了,解决这个问题的方法很简单,在循环体外面创建单元格格式contextstyle(即把它当成一个“全局”变量),不要在循环内部创建。

  正确的代码如下:

 / * 导出Excel-2015年11月11日 * *@param outPutParam Excel数据实体,包括要导出的excel标头、列标题、数据等 * */ private void createContentRows(ExcelParam outPutParam) { HSSFWorkbook workbook=new HSSFWorkbook(); //创建一个Excel文件 HSSFCellStyle contextstyle =workbook.createCellStyle(); // 遍历集合数据,产生数据行 for (int i = 0; i < outPutParam.getContent().size(); i++) { int rowIndex = i + 2; HSSFRow contentRow = sheet.createRow(rowIndex); Map 
       
         rowDate = outPutParam.getContent().get(i); //遍历列 for (int j = 0; j < outPutParam.getTitleList().size(); j++) { Title headTitle = outPutParam.getTitleList().get(j);//获取第i行第j列列标题 String headerName = headTitle.getName();//获取第j列列标识 Object data = rowDate.get(headerName);//获取第i行第j列所放数据 HSSFCell contentCell = contentRow.createCell(j); Boolean isNum = false;//data是否为数值型 Boolean isInteger=false;//data是否为整数 Boolean isPercent=false;//data是否为百分数 if (data != null || "".equals(data)) { //判断data是否为数值型 isNum = data.toString().matches("^(-?\\d+)(\\.\\d+)?$"); //判断data是否为整数(小数部分是否为0) isInteger=data.toString().matches("^[-\\+]?[\\d]*$"); //判断data是否为百分数(是否包含“%”) isPercent=data.toString().contains("%"); } //如果单元格内容是数值类型,涉及到金钱(金额、本、利),则设置cell的类型为数值型,设置data的类型为数值类型 if (isNum && !isPercent) { HSSFDataFormat df = workbook.createDataFormat(); // 此处设置数据格式 if (isInteger) { contextstyle.setDataFormat(df.getBuiltinFormat("#,#0"));//数据格式只显示整数 }else{ contextstyle.setDataFormat(df.getBuiltinFormat("#,0.00"));//保留两位小数点 } // 设置单元格格式 contentCell.setCellStyle(contextstyle); // 设置单元格内容为double类型 contentCell.setCellValue(Double.parseDouble(data.toString())); } else { contentCell.setCellStyle(contextstyle); // 设置单元格内容为字符型 contentCell.setCellValue(data.toString()); } } } } 
       

  最后导出的正确格式:

这里写图片描述








版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216343.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午12:03
下一篇 2026年3月18日 下午12:03


相关推荐

  • python学习—— IPy 强大的IP地址解析模块

    python学习—— IPy 强大的IP地址解析模块       最近在忙着做计算机网络的课程设计,打算写一个可以扫描内网主机的扫描工具。学习过程中安利到了许多python新姿势,IPy模块就是其中一个。1.IPy模块。       在IP地址规划中,涉及到计算大量的IP地址,包括网段、网络掩码、广播地址、…

    2025年6月23日
    4
  • navicat for mysql注册码激活_navicat注册激活

    navicat for mysql注册码激活_navicat注册激活打开navicatformysql接着打开帮助,选中注册,把下面的复制上去就可以了NAVH-WK6A-DMVK-DKW3 

    2022年10月10日
    3
  • java轻量级web框架_什么是框架

    java轻量级web框架_什么是框架JEMSF框架前言今天我们准备向广大开发人员推荐一种新的框架,暂时取名JEMSF,如果您已经对Struts、Tapestry以及Spring和Hibernat有一些了解,那么应该可以更好的理解下面的文章,JEMSF是我在工作生涯中最大的一个创造,经历了很多考验和应用的试验,最后形成JEMSF。序一种新的事物的诞生需要经历很多的考验,我自认为JEMSF是一个很好的WEB应用框架,很久以前(2…

    2025年9月30日
    5
  • MiniMax×腾讯云:百万级Agent RL沙箱落地,激活成功教程智能体规模化应用痛点

    MiniMax×腾讯云:百万级Agent RL沙箱落地,激活成功教程智能体规模化应用痛点

    2026年3月19日
    2
  • Spring Boot Starters启动器

    Spring Boot Starters启动器文章目录 Starters 是什么 Starters 命名 Starters 分类 1 SpringBoot 应用类启动器 2 SpringBoot 生产启动器 3 SpringBoot 技术类启动器 Starters 是什么 Starters 可以理解为启动器 它包含了一系列可以集成到应用里面的依赖包 你可以一站式集成 Spring 及其他技术 而不需要到处找示例代码和依赖包 如你想使用 SpringJPA 访问数据库 只要加入 spring boot starter data jpa 启动器依赖就能使用了 Starters

    2026年3月17日
    2
  • webstorm 2022.01.13 激活码【2021最新】

    (webstorm 2022.01.13 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/ide…

    2022年3月31日
    123

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号