首页 > 其他分享 >使用easypoi模板导出遇见的bug

使用easypoi模板导出遇见的bug

时间:2023-08-01 10:11:55浏览次数:32  
标签:导出 excel fe new easypoi bug 模板

一、前言

easypoi是为java提供的一款excel导入导出的工具包。使用easypoi,能极大的简化我们excel导入导出的操作;但是在使用过程中,也发现了一些bug,在这里做一些相关记录。

二、问题

我这里发现的问题主要是easypoi提供的模板导出功能。

1.前期准备

为了模拟问题的出现,我们需要新建一个Springboot项目,然后引入相关依赖,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>demo</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.1.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

我是用的easypoi版本为4.1.3。
接着,我们再创建两个实体类,如下:

package com.example.demo.entity;
import lombok.Data;

@Data
public class Student {
    private Integer id;
    private String stuName;
}
package com.example.demo.entity;
import lombok.Data;
import java.util.List;
@Data
public class Teacher {
    private Integer id;
    private String name;
    List<Student> stuList;
}

两个实体类,一个Teacher类一个Student类,Teacher与Student的关系是一对多的关系。

最后,我们在resources目录下的templates文件夹下,新增一个空白的名字为导出模板.xlsx的文件作为我们的导出模板,如下:
新建的excel导出模板

1.循环嵌套某些单元格值为空的情况

首先,修改我们的导出模板.xlsx如下:
导出模板

导出模板语法在这里我就不多说了,详情请参考easypoi模板语法

接着,编写我们的测试方法。

    @Test
    void contextLoads() throws Exception{
        /**
         * 生成需要导出的数据
         */
        List<Teacher> teacherList =  new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Teacher t = new Teacher();
            t.setId(i);
            t.setName("教师_" + i);
            List<Student> studentList = new ArrayList<>();
            for (int j = 0; j < 3; j++) {
                Student student = new Student();
                student.setId(j);
                student.setStuName("学生_" + i + "_" + j);
                studentList.add(student);
            }
            t.setStuList(studentList);
            teacherList.add(t);
        }

        /**
         * 加载excel模板
         */
        TemplateExportParams params = new TemplateExportParams(
                "templates/导出模板.xlsx", true);
        Map<String, Object> map = new HashMap<String, Object>();
        /**
         * 这个map的key需要和模板里便利的值保持一直
         */
        map.put("list", teacherList);
        
        Workbook book = ExcelExportUtil.exportExcel(params, map);
        File savefile = new File("D:/home/excel/");
        if (!savefile.exists()) {
            savefile.mkdirs();
        }
        FileOutputStream fos = new FileOutputStream("D:/home/excel/exportTemp.xlsx");
        book.write(fos);
        fos.close();
    }

注意:模板里遍历的列表名及对应属性需要和代码中的属性保持一致!

注意

执行我们的测试方法,最终生成的excel如下:

问题

从上图中不难发现,教师0应该也有三个学生,但是最终只显示出一个,其他的两个直接为空白!

2.问题解决

数据丢了两行,我们怎么解决呢?解决方法很简单,只要将模板里面的$fe替换为fe就可以了,修改之后的模板如下:
修改之后的模板

这里补充说明一下,$fefe的区别。
fe:在处理数据时,会在插入数据的下方生成一个空行
$fe:会在插入数据的下方保留原有数据

这里其实是easypoi的一个bug,在处理一对多数据的时候,使用$fe会有空行的问题。

再次运行我们的测试程序,得到的结果如下:
修改之后的结果

我们不难发现,原先为空的数据现在全部都展示了。

3.新的问题

解决了上述问题,又有新的问题产生了,如果我们的要求就是需要在列表下方保留一列,比如加一个合计列,这时我们该怎么处理呢?
在这里我说一下我的解决方案。
通过Workbook book = ExcelExportUtil.exportExcel(params, map);方法返回的Workbook对象,获取到sheet对象,在通过sheet对象获取excel中数据的行数,在获取到的行数中插入我们的代码。修改测试类中代码如下:

    @Test
    void contextLoads() throws Exception{
        /**
         * 生成需要导出的数据
         */
        List<Teacher> teacherList =  new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Teacher t = new Teacher();
            t.setId(i);
            t.setName("教师_" + i);
            List<Student> studentList = new ArrayList<>();
            for (int j = 0; j < 3; j++) {
                Student student = new Student();
                student.setId(j);
                student.setStuName("学生_" + i + "_" + j);
                studentList.add(student);
            }
            t.setStuList(studentList);
            teacherList.add(t);
        }

        /**
         * 加载excel模板
         */
        TemplateExportParams params = new TemplateExportParams(
                "templates/导出模板.xlsx", true);
        Map<String, Object> map = new HashMap<String, Object>();
        /**
         * 这个map的key需要和模板里便利的值保持一直
         */
        map.put("list", teacherList);

        Workbook book = ExcelExportUtil.exportExcel(params, map);

        /**
         * 1.首先获取sheet
         * 2.通过获取到的sheet获取excel的函数
         * 3.在指定行创建单元格并设置值
         */
        Sheet sheetAt = book.getSheetAt(0);

        /**********************添加合计行的代码开始************************************/
        // 设置单元格样式
        CellStyle cellStyle = book.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);//设置水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//设置垂直居中

        int physicalNumberOfRows = sheetAt.getPhysicalNumberOfRows();
        Row row = sheetAt.createRow(physicalNumberOfRows);
        Cell cell01 = row.createCell(0);
        cell01.setCellStyle(cellStyle);
        cell01.setCellValue("合计");
        /***********************添加合计行的代码结束*******************************/


        File savefile = new File("D:/home/excel/");
        if (!savefile.exists()) {
            savefile.mkdirs();
        }
        FileOutputStream fos = new FileOutputStream("D:/home/excel/exportTemp.xlsx");
        book.write(fos);
        fos.close();

    }

运行我们的测试程序,结果如下:
添加合计之后的结果

可以发现我们的合计列加上了。
这是我自己想到的解决方案,如果大家有更好的解决方案,欢迎大家在评论区评论。

三、总结

在使用easypoi的模板导出功能时,如果导出的数据包含一对多的情形,此时使用$fe是由bug的,可能会产生空行的问题,此时建议使用fe替换$fe。如果列表下面还需要保留数据,需要我们通过Workbook对象,手动插入相关数据。

标签:导出,excel,fe,new,easypoi,bug,模板
From: https://www.cnblogs.com/xshangao/p/17593951.html

相关文章

  • A_S の 模板库
    目录I数据结构&树0x10树链剖分0x11LCA0x12LCT0x13splay&平衡树0x14李超线段树0x15线段树0x16树状数组0x17可持久化线段树0x18可持久化01trie0x19分块0x1A单调栈0x1B树套树II动态规划III数学0x30线性基IV多项式V图论VI平面几何VII常见套路&模板组合这里......
  • VC6.0 dll debug
    现象是用debug中的stepinfo或者runtocursor合着设置断点会出现Oneormorebreakpointscannotbesetandhavebeendisabled. Executionwillstopatthebeginningoftheprogram.解决方法,1.在project->setting->c/c++-general->debuginfo->programdatabsefored......
  • 【个人模板封装】树套树、高维数据结构
    前言这是我个人使用的一些模板封装,限于个人能力,可能存在诸多不足与漏洞,在未加测试直接使用前请务必小心谨慎。更新可能会滞后于我本地的文档,如有疑问或者催更之类的可以在评论区留言。全文模板测试均基于以下版本信息,请留意版本兼容问题。Windows,64bitG++(ISOC++20)stack......
  • P3375 【模板】KMP 字符串匹配 题解
    前言狗屁不是,建议别看!!! 题目链接P3375【模板】KMP字符串匹配-洛谷|计算机科学教育新生态(luogu.com.cn) 分析先给个例子s1:ABCABCABBs2:ABCABB若使用朴素算法匹配,当匹配到s1:ABCABCABBs2:ABCABB时,朴素算法会跳出,然后匹配下一位。最终匹配到s1:ABCABCABBs2:......
  • Manacher模板,支持自定义不同字符的相等关系
    #include<bits/stdc++.h>usingnamespacestd;structManacher{  structChar{    charch;    Char(){}    Char(charch):ch(ch){}    Char&operator=(constchar&r){      ch=r;      ret......
  • nacos安装启动过程遇到的BUG
    1、Nacos启动报错Unabletostartwebserver……UnabletostartembeddedTomcatnacos启动报错:集群启动报这个错误,改为单机启动用记事本打开bin目录下查看startup.cmd把 setMODE="cluster"改为 setMODE="standalone"即可2、springboot集成启动报错Considerdefinin......
  • 6.Pod的资源配置模板
    资源范式:五个一级字段kind:<String>指明对象的类型(资源类型),类型标签apiVersion:<String>指明对象的类型(资源类型),类型隶属的API群组metadata:<Object>对象元数据,名称/标签/注解和隶属的名称空间spec:<Object>对象数据,期望状态status:<Object>资源的实际状态,由系......
  • 如何开发一套苹果cms前端模板
    本文运用了苹果cms官网的模板开发教程,开发了一套苹果cms的前端模板,感兴趣的同学可以去github下载使用。什么是模板模板是网站的主题外观,也被称为主题或皮肤。通过使用不同的模板,网站的前台可以以不同的样式展示。这就像人们的服装一样,人们打扮得漂亮会吸引人,同样地,一个好看的......
  • Attention机制竟有bug?Softmax是罪魁祸首,影响所有Transformer
    前言 「大模型开发者,你们错了。」本文转载自机器之心仅用于学术分享,若侵权请联系删除欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结、最新技术跟踪、经典论文解读、CV招聘信息。CV各大方向专栏与各个部署框架最全教程整理【CV技术指南】CV全栈指导班、基础入门班、论......
  • 【模板】数论基础:exGCD,exCRT,inverse,Lucas,BSGS,primitive root
    7.29数论WIP\(a\equivb\pmodp\Rightarrow\frac{a}{d}\equiv\frac{b}{d}\pmod{\frac{p}{d}},d=\gcd(a,b,p)\)。exGCD若\((a,b)=1\),则\(0\leqx<b\),\(ax\bmodb\)互不相同,有一个是\(1\)。证明:\(ax_1\equivax_2\pmodb\)则\((x_1-x_2)a|b\),因为......