【Java】将数据纵横转换,导出为excel文件,并实现动态表头


前言

最近碰到了一个需求,需要维护一个问卷内容,问卷的问题都是动态的。并且要把每个用户回答的内容给他导出为excel。下图就是最后实现的样子。
在这里插入图片描述
看起来还是有点难度的,网上去搜将数据纵横转换,但是大多都固定表头,没办法实现我需要动态表头。我这前面的姓名年龄等个人信息都是固定的,但是后面的问题是动态的,维护了N个问题,就有N个表头;下面一起来看看代码吧;直接代码里加注解解释,不过多解释!!!


一、pom文件

我这是用hutool的工具类的,大家可以去hutool官网看看

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.4.5</version>
        </dependency>

二、实体类,数据表

1.BcsQuesetionnaireDetail

这是问题的具体信息表,也就这个表内的问题决定着动态的表头问题(表我就不贴了,直接上实体类)

package com.example.whwechat.bean;

import lombok.Data;

/**
 * @author 孤巷.
 * @description
 * @date 2024/3/12 上午 10:03
 */
@Data
public class BcsQuesetionnaireDetail {
    private Integer id;

    /**
     * 问卷类型编码
     */
    private String quesetionCode;

    /**
     * 问题编码
     */
    private String problemCode;

    /**
     * 问题
     */
    private String problemName;

    /**
     * 回答是后是否可继续检查(0:是,1:否)
     */
    private Integer answerTrue;

    /**
     * 回答否后是否可继续检查(0:是,1:否)
     */
    private Integer answerFalse;

    /**
     * 是否终止流程,并弹出提示框(0:否,1:是)
     */
    private Integer teremination;

    /**
     * 终止后提示框内容
     */
    private String message;

    /**
     * 问题排序
     */
    private Integer sort;

    /**
     * 是否启用(0:启用,1:关闭)
     */
    private Integer active;
}

2.BcsQuesetionnaireAnswerModel

这是用户回答问题信息的存储表,我这是个model组合查询出来的,和用户表关联的;

package com.example.whwechat.model;

import lombok.Data;

/**
 * @author 孤巷.
 * @description
 * @date 2024/3/9 下午 3:55
 */
@Data
public class BcsQuesetionnaireAnswerModel {

    /**
     * 用户单次回答编码
     */
    String problemUid;

    /**
     * 注册时间
     */
    String inputTime;

    /**
     * 卡号
     */
    String cardNo;

    /**
     * 姓名
     */
    String userName;

    /**
     * 年龄
     */
    int age;

    /**
     * 用户电话
     */
    String userPhone;

    /**
     * 是否成功预约
     */
    int nstatus;

    /**
     * 问题编码
     */
    String problemCode;

    /**
     * 问题回复(0:否,1:是)
     */
    int answer;
}

3.BcsQuesetionnaireUser

这是用户信息表,也就是说每个用户单次保存问卷回答的时候,会存储进来一条信息,并且生成一个problemUid 这是单次回答的唯一标识(因为我这边的需求是一个人可以多次回答问题);通过problemUid与具体回答信息表关联就可以取到一个用户,每个问题回答的内容是什么;

package com.example.whwechat.bean;

import lombok.Data;

import java.util.List;

/**
 * @author 孤巷.
 * @description
 * @date 2024/3/9 上午 11:57
 */
@Data
public class BcsQuesetionnaireUser {
    private Integer id;

    private String insertTime;

    /**
     * 单次回答ID标识
     */
    private String problemUid;

    /**
     * 问卷类型编码
     */
    String quesetionCode;

    /**
     * 小程序openId-用户标识
     */
    private String openid;

    /**
     * 卡号
     */
    private String cardNo;

    /**
     * 用户姓名
     */
    private String userName;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 用户联系号码
     */
    private String userPhone;

    /**
     * 是否成功预约(0:否,1:是)
     */
    private Integer status;

    List<BcsQuesetionnaireAnswer> answerList;


}

三、实现业务代码

    public void getExcelExport() {
        //问题列表
        List<BcsQuesetionnaireDetail> quesetionnaireList = bcsQuesetionnaireDetailDao.getByActiveOrderBySort(0, "");
        //用户回复问题信息
        List<BcsQuesetionnaireAnswerModel> answerList = bcsQuesetionnaireUserDao.getBcsQuesetionnaireAnswerInfor(null);
        //用户信息
        List<BcsQuesetionnaireUser> userList = bcsQuesetionnaireUserDao.getAllOrderByInsertTime();
        List<Map<String, Object>> list = new ArrayList<>();
        //先遍历用户信息
        for (BcsQuesetionnaireUser userModel : userList) {
            //这里用map是因为我根据hutool官网的map创建excel改造而来的;他那是固定表头
            Map<String, Object> map = new TreeMap<>();
            //这几个参数都是固定的,所以我也就给他固定起来了,加上数字是为了排序(TreeMap)
            map.put("1.姓名", userModel.getUserName());
            map.put("2.年龄", userModel.getAge());
            map.put("3.手机号码", userModel.getUserPhone());
            map.put("4.卡号", userModel.getCardNo());
            //现在开始遍历用户回复信息
            for (BcsQuesetionnaireAnswerModel answerModel : answerList) {
                //接着遍历问题列表
                for (BcsQuesetionnaireDetail quesetionnaireDetailModel : quesetionnaireList) {
                    //利用问题编码+用户单次回答的uid来判断是否是同一个问题
                    if (quesetionnaireDetailModel.getProblemCode().equals(answerModel.getProblemCode()) && answerModel.getProblemUid().equals(userModel.getProblemUid())) {
                        //这里就是动态问题的表头了,map的key就是问题表头,value就是内容
                        log.info("对比进来的结果,回复{},问题{}", answerModel, quesetionnaireDetailModel);
                        map.put(quesetionnaireDetailModel.getProblemName(), answerModel.getAnswer());
                        map.put("5.是否成功预约", answerModel.getNstatus());
                    }
                }
            }
            //这个不要漏了,一个用户一条数据
            list.add(map);
        }
        //把数据放进去进行生成excel
        ArrayList<Map<String, Object>> rows = CollUtil.newArrayList(list);
        // 通过工具类创建writer(excel的文件地址,你也可以改成流的方式 返回给前段)
        ExcelWriter writer = ExcelUtil.getWriter("d:/writeMapTest.xlsx");
        // 合并单元格后的标题行,使用默认标题样式
        writer.merge(rows.size(), "问卷调查档案");
        Set<String> key = rows.get(0).keySet();
        for (int i = 0; i < key.size(); i++) {
            for (String keys : key) {
                int keyLength = keys.length(); // 获取key的长度
                writer.setColumnWidth(i, keyLength * 2);
            }
        }

        // 一次性写出内容,使用默认样式,强制输出标题
        writer.write(rows, true);
        // 关闭writer,释放内存
        writer.close();
    }

再来一个最后实现结果
在这里插入图片描述


总结

主要就是利用hutool的使用map创建excel的方式,对他进行稍加改造。然后实现动态表头的目的;

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值