【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


目录
打赏
0
0
0
0
6
分享
相关文章
|
3月前
|
使用OpenPyXL库实现Excel单元格其他对齐方式设置
本文介绍了如何使用Python的`openpyxl`库设置Excel单元格中的文本对齐方式,包括文本旋转、换行、自动调整大小和缩进等,通过具体示例代码展示了每种对齐方式的应用方法,适合需要频繁操作Excel文件的用户学习参考。
204 85
使用OpenPyXL库实现Excel单元格其他对齐方式设置
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
218 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
5月前
如何设置Excel的快捷键?
【10月更文挑战第19天】如何设置Excel的快捷键?
609 8
导出excel的两个方式:前端vue+XLSX 导出excel,vue+后端POI 导出excel,并进行分析、比较
这篇文章介绍了使用前端Vue框架结合XLSX库和后端结合Apache POI库导出Excel文件的两种方法,并对比分析了它们的优缺点。
1717 0
|
5月前
|
Apache POI java对excel表格进行操作(读、写) 有代码!!!
文章提供了使用Apache POI库在Java中创建和读取Excel文件的详细代码示例,包括写入数据到Excel和从Excel读取数据的方法。
338 0
【Python】已解决:Python pandas读取Excel表格某些数值字段结果为NaN问题
【Python】已解决:Python pandas读取Excel表格某些数值字段结果为NaN问题
702 0
如何在Spring Boot框架下实现高效的Excel服务端导入导出?
ArtifactId:是项目的唯一标识符,在实际开发中一般对应项目的名称,就是项目根目录的名称。 Group Id,Artfact Id是保证项目唯一性的标识,一般来说如果项目打包上传至maven这样的包管理仓库中。在搜索你的项目时,Group Id,Artfact Id是必要的条件。 Version:版本号,默认0.0.1-SNAPSHOT。SNAPSHOT代表不稳定的版本,与之相对的有RELEASE。 Project type:工程的类型,maven工程还是gradle工程。 Language:语言(Java,Kotlin,Groovy)。
Apache POI与easyExcel:Excel文件导入导出的技术深度分析
Apache POI与easyExcel:Excel文件导入导出的技术深度分析
从Excel到Hadoop:数据规模的进化之路
从Excel到Hadoop:数据规模的进化之路
39 10
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等