JAVA一对多EXCEL导出

作者: adm 分类: java 发布时间: 2021-08-08

在实际开发中,数据库里面一对多的形式是普遍的事情,比如本次业务中,是一个举报模块,首先需要填写举报人信息,然后可以举报多个员工或者合作伙伴,那么这里就是一个举报人对应多个员工或者合作伙伴。

在后台管理页面里的表格里,我是每行只展示的举报人的消息,通过添加一个“查看详情”的按钮,可以打开新的页面查看被举报人的详细信息,这样算是比较合理的。但是需要对这些信息做一个Excel导出功能的话,该怎么在Excel里展示信息比较合理呢?我想到的就是合并单元格的形式。首先看看后台页面的展示情况:
在这里插入图片描述

现在利用EasyPoi这个三方库实现的是导出功能能够合并单元格,EasyPoi官方文档

实现

StaffExcel类,即被举报员工信息类

@Data
@Accessors(chain = true)
@ExcelTarget("ReportInfoExcel")
public class StaffExcel {
    @Excel(name = "id",isColumnHidden = true)
    private String id;

    @Excel(name = "姓名", width = 20)
    private String username;

    @Excel(name = "工号", width = 20)
    private String cardNum;

    @Excel(name = "部门", width = 20)
    private String dept;

    @Excel(name = "职位", width = 20)
    private String position;
}

PartnerExcel类,即被举报合作伙伴类

@Data
@Accessors(chain = true)
@ExcelTarget("ReportInfoExcel")
public class PartnerExcel {
    @Excel(name = "id",isColumnHidden = true)
    private String id;

    @Excel(name = "姓名", width = 20)
    private String username;

    @Excel(name = "职位", width = 20)
    private String position;

    @Excel(name = "公司", width = 20)
    private String company;
}

Excel要展示的实体类,即举报人信息和被举报人的一对多VO类

@Data
@Accessors(chain = true)
public class ReportInfoExcel {
    //isColumnHidden表示此栏是否在Excel表里面展示
    @Excel(name = "id",isColumnHidden = true,needMerge = true)
    private String id;
	//needMerge一定要加
    @Excel(name = "举报人姓名", width = 20, needMerge = true)
    private String reportUsername;

    @Excel(name = "手机号", width = 20, needMerge = true)
    private String tel;

    @Excel(name = "邮箱", width = 20, needMerge = true)
    private String email;

    @ExcelCollection(name = "举报员工信息")
    private List<StaffExcel> staffExcels;

    @ExcelCollection(name = "举报合作伙伴信息")
    private List<PartnerExcel> partnerExcels;
}

Controller

    @GetMapping("export")
    public void export(HttpServletResponse response) {
        try {
            // 设置响应输出的头类型
            response.setHeader("content-Type", "application/vnd.ms-excel");
            // 设置下载的Excel名称,以当前时间为文件后缀,DateUtil为Hutool工具包里的工具类
            String dateTime = DateUtil.formatDateTime(new Date());
            String fileName = "user"+dateTime+".xls";
            response.setHeader("Content-Disposition", "attachment;filename="+fileName);
            // excel信息部分
            List<ReportInfoExcel> exportList = new LinkedList<>();
            //此处为了演示,手动输入的数据,没有从数据库查数据,实际开发中从数据库中查数据
            //创建ReportInfoExcel中List<StaffExcel>对象
            List<StaffExcel> staffList = new LinkedList<>();
            StaffExcel staff = new StaffExcel();
            staff.setId("1")
                    .setUsername("李四")
                    .setCardNum("123456789")
                    .setDept("开发部门")
                    .setPosition("java开发");
            //这里往list中加了两次staffExcel,模拟一对多的关系
            staffList.add(staff);
            staffList.add(staff);

            //创建ReportInfoExcel中List<PartnerExcel>对象
            List<PartnerExcel> partnerList = new LinkedList<>();
            PartnerExcel partner = new PartnerExcel();
            partner.setId("2")
                    .setUsername("张三")
                    .setCompany("微软公司")
                    .setPosition("java开发");
            //这里往list中加了两次staffExcel,模拟一对多的关系
            partnerList.add(partner);
            partnerList.add(partner);
            partnerList.add(partner);

            ReportInfoExcel reportInfo = new ReportInfoExcel();
            reportInfo.setId("2")
                    .setTel("132********")
                    .setEmail("77@qq.com")
                    .setReportUsername("王五")
                    //将上面创建的list对象添加进去
                    .setPartnerExcels(partnerList)
                    .setStaffExcels(staffList);
            //reportInfo代表一行数据,exportList则是reportInfo的list集合,这里测试三行
            exportList.add(reportInfo);
            exportList.add(reportInfo);
            exportList.add(reportInfo);

            ExportParams exportParams = new ExportParams();
            // 设置sheet得名称
            exportParams.setSheetName("员工报表1");

            Map<String, Object> map = new HashMap<>();
            // title的参数为ExportParams类型,目前仅仅在ExportParams中设置了sheetName
            map.put("title", exportParams);
            // 模版导出对应得实体类型,即包含了List的对象
            map.put("entity", ReportInfoExcel.class);
            // sheet中要填充得数据
            map.put("data", exportList);

            List<Map<String, Object>> sheetsList = new ArrayList<>();
            sheetsList.add(map);
            //创建excel文件的方法
            Workbook workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF);
            //通过response输出流直接输入给客户端
            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

测试下载好的Excel文档:
在这里插入图片描述
以上这些代码,直接复制进项目里面,再调export这个接口就可以直接实现下载,可以试一试。

后记

开发中也遇到了一个问题,下载后的Excel文件排序有问题,如下图:
在这里插入图片描述
上图中总是会有多行,调试了多种还是不行,最后发现是ReportInfoExcel类中的id字段没有加needMerge=true,本来以为这个字段用了isColumnHidden = true就不会再Excel中展示了所以没在意,最后排查了一个小时才找到原因,所以一定要记住,一对多情况下,这个“一”里面的所以字段都要加上needMerge=true。

用EasyPoi实现Excel表格的下载对比传统的Workbook或者阿里的EasyExcel确实还是挺简单易用的,而且利用response直接输出生成好的文件,比传统的先生成Excel文件到磁盘,再调一次接口去下载形式更简便,也省去了磁盘空间的占用,具体的@Excel之类的注解可以查看官方文档,里面还有很多别的功能,需要的时候也可以使用。

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!