文章目录
前言
最近碰到了一个需求,需要维护一个问卷内容,问卷的问题都是动态的。并且要把每个用户回答的内容给他导出为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的方式,对他进行稍加改造。然后实现动态表头的目的;