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

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

背 景


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

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


28.png

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



 通过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<String, Object> 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)方法即可。


29.png


优化


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


 如果数据量大的话,系统可能会报错“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<String, Object> 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());
        }
      }
    }
  }


  最后导出的正确格式:

30.png


相关文章
Excel中如何批量重命名工作表与将每个工作表导出到单独Excel文件
本文介绍了如何在Excel中使用VBA批量重命名工作表、根据单元格内容修改颜色,以及将工作表导出为独立文件的方法。同时提供了Python实现导出工作表的代码示例,适用于自动化处理Excel文档。
|
数据格式 UED
记录一次NPOI库导出Excel遇到的小问题解决方案
【11月更文挑战第16天】本文记录了使用 NPOI 库导出 Excel 过程中遇到的三个主要问题及其解决方案:单元格数据格式错误、日期格式不正确以及合并单元格边框缺失。通过自定义单元格样式、设置数据格式和手动添加边框,有效解决了这些问题,提升了导出文件的质量和用户体验。
1281 3
|
前端开发
实现Excel文件和其他文件导出为压缩包,并导入
实现Excel文件和其他文件导出为压缩包,并导入
514 1
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
1280 4
|
Java API Apache
如何根据Excel某列数据为依据分成一个新的工作表
在处理Excel数据时,我们常需要根据列值将数据分到不同的工作表或文件中。本文通过Python和VBA两种方法实现该操作:使用Python的`pandas`库按年级拆分为多个文件,再通过VBA宏按班级生成新的工作表,帮助高效整理复杂数据。
|
数据采集 数据可视化 数据挖掘
用 Excel+Power Query 做电商数据分析:从 “每天加班整理数据” 到 “一键生成报表” 的配置教程
在电商运营中,数据是增长的关键驱动力。然而,传统的手工数据处理方式效率低下,耗费大量时间且易出错。本文介绍如何利用 Excel 中的 Power Query 工具,自动化完成电商数据的采集、清洗与分析,大幅提升数据处理效率。通过某美妆电商的实战案例,详细拆解从多平台数据整合到可视化报表生成的全流程,帮助电商从业者摆脱繁琐操作,聚焦业务增长,实现数据驱动的高效运营。
|
存储 安全 大数据
网安工程师必看!AiPy解决fscan扫描数据整理难题—多种信息快速分拣+Excel结构化存储方案
作为一名安全测试工程师,分析fscan扫描结果曾是繁琐的手动活:从海量日志中提取开放端口、漏洞信息和主机数据,耗时又易错。但现在,借助AiPy开发的GUI解析工具,只需喝杯奶茶的时间,即可将[PORT]、[SERVICE]、[VULN]、[HOST]等关键信息智能分类,并生成三份清晰的Excel报表。告别手动整理,大幅提升效率!在安全行业,工具党正碾压手动党。掌握AiPy,把时间留给真正的攻防实战!官网链接:https://www.aipyaipy.com,解锁更多用法!
|
数据采集 数据可视化 数据挖掘
利用Python自动化处理Excel数据:从基础到进阶####
本文旨在为读者提供一个全面的指南,通过Python编程语言实现Excel数据的自动化处理。无论你是初学者还是有经验的开发者,本文都将帮助你掌握Pandas和openpyxl这两个强大的库,从而提升数据处理的效率和准确性。我们将从环境设置开始,逐步深入到数据读取、清洗、分析和可视化等各个环节,最终实现一个实际的自动化项目案例。 ####
3113 10
|
数据采集 存储 JavaScript
自动化数据处理:使用Selenium与Excel打造的数据爬取管道
本文介绍了一种使用Selenium和Excel结合代理IP技术从WIPO品牌数据库(branddb.wipo.int)自动化爬取专利信息的方法。通过Selenium模拟用户操作,处理JavaScript动态加载页面,利用代理IP避免IP封禁,确保数据爬取稳定性和隐私性。爬取的数据将存储在Excel中,便于后续分析。此外,文章还详细介绍了Selenium的基本设置、代理IP配置及使用技巧,并探讨了未来可能采用的更多防反爬策略,以提升爬虫效率和稳定性。
1105 4

热门文章

最新文章