java
<!-- poi-tl导出word文档-->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.1</version>
</dependency>
以下是需要的实体类
java
package com.dream.domain.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
public class QuestionVo implements Serializable {
private String quesTitle;
private int type;
private String numb;
private ArrayList<AnwserVo> anwser;
}
java
package com.dream.domain.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class AnwserVo implements Serializable {
private String content;
private int type;
private int supplementType;
private String supplement;
}
以下是实现逻辑
java
package com.dream.controller.file;
import com.deepoove.poi.XWPFTemplate;
import com.dream.common.BussinessException;
import com.dream.common.Result;
import com.dream.domain.vo.AnwserVo;
import com.dream.domain.vo.PageVo;
import com.dream.domain.vo.QuestionVo;
import com.dream.domain.vo.Student;
import com.dream.service.admin.QuestionnaireAdminService;
import com.dream.service.admin.UserMangeAdminService;
import com.dream.utils.Utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@RestController
@RequestMapping("file")
public class FileUploadController {
private final ResourceLoader resourceLoader;
@Autowired
private QuestionnaireAdminService questionnaireAdminService;
// 通过构造函数注入ResourceLoader
public FileUploadController(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
/**
* 将数据赋值到多个文档里,并将多个word放入压缩包并下载
* @param idsString
* @param response
*/
@GetMapping("/exportBatch")
public void exportBatchStudents(@RequestParam("idsString") String idsString, HttpServletResponse response) {
List<Integer> ids = new ArrayList<>();
ObjectMapper mapper = new ObjectMapper();
try {
if(idsString != null && !"".equals(idsString)){
ids = mapper.readValue(idsString, new TypeReference<List<Integer>>() {});
}
} catch (JsonProcessingException e) {
throw new BussinessException("导出问卷调查word列表压缩包,传入参数有误");
}
String name = Utils.dateToString("yyyy-MM-dd");
try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
response.setContentType("application/zip");
response.setCharacterEncoding("UTF-8");
String zipName = URLEncoder.encode(name+" 问卷调查.zip", StandardCharsets.UTF_8.toString());
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + zipName);
for (Integer id : ids) {
try {
// 1. 获取模板资源
Resource resource = resourceLoader.getResource("classpath:templates/question.docx");
if (!resource.exists()) throw new FileNotFoundException("模板文件未找到");
// 2. 查询数据
Map<String, ArrayList<QuestionVo>> result = questionnaireAdminService.queryUserQuestionnaireById(id);
ArrayList<QuestionVo> list = result.get("subject");
Map<String, String> data = new HashMap<>();
// 3. 填充数据(完整迁移原有逻辑)
if (list != null && !list.isEmpty()) {
Map<String, Object> nameMap = questionnaireAdminService.queryNameByQuestionnaireId(id);
String fileName = (nameMap != null && nameMap.get("name") != null) ?
(String) nameMap.get("name") : "未知用户_" + id;
// 核心数据填充逻辑(与单个导出完全一致)
for (QuestionVo questionVo : list) {
List<AnwserVo> anwser = questionVo.getAnwser();
switch (questionVo.getNumb()) {
case "one":
for (int j = 0; j < anwser.size(); j++) {
AnwserVo anwserVo = anwser.get(j);
if (anwserVo.getType() == 1) {
data.put("one_" + j, "√");
}
}
break;
case "two":
for (int j = 0; j < anwser.size(); j++) {
AnwserVo anwserVo = anwser.get(j);
if (anwserVo.getType() == 1) {
data.put("two_" + j, "√");
}
if (anwserVo.getSupplementType() == 1) {
data.put("two_supplement", anwserVo.getSupplement());
}
}
break;
case "three":
for (int j = 0; j < anwser.size(); j++) {
AnwserVo anwserVo = anwser.get(j);
if (anwserVo.getType() == 1) {
data.put("three_" + j, "√");
}
}
break;
case "four":
for (int j = 0; j < anwser.size(); j++) {
AnwserVo anwserVo = anwser.get(j);
if (anwserVo.getType() == 1) {
data.put("four_" + j, "√");
}
if (anwserVo.getSupplementType() == 1) {
data.put("four_supplement", anwserVo.getSupplement());
}
}
break;
case "five":
for (int j = 0; j < anwser.size(); j++) {
AnwserVo anwserVo = anwser.get(j);
if (anwserVo.getType() == 1) {
data.put("five_" + j, "√");
}
}
break;
case "six":
for (int j = 0; j < anwser.size(); j++) {
AnwserVo anwserVo = anwser.get(j);
if (anwserVo.getType() == 1) {
data.put("six_" + j, "√");
}
if (anwserVo.getSupplementType() == 1) {
data.put("six_supplement", anwserVo.getSupplement());
}
}
break;
}
}
// 4. 生成文档并写入ZIP
try (XWPFTemplate template = XWPFTemplate.compile(resource.getInputStream()).render(data)) {
String entryName = URLEncoder.encode(fileName + ".docx", "UTF-8").replaceAll("\\+", "%20");
zos.putNextEntry(new ZipEntry(entryName));
template.write(zos);
zos.closeEntry();
}
}
} catch (Exception e) {
// 继续处理下一个问卷
}
}
} catch (IOException e) {
throw new RuntimeException("压缩包生成失败: " + e.getMessage(), e);
}
}
}
java
/**
* 查询用户的问卷调查通过id service层
* @return
*/
@Override
public Map<String, ArrayList<QuestionVo>> queryUserQuestionnaireById(Integer id) {
try {
Map<String, Object> map1 = questionnaireAdminMapper.queryUserQuestionnaireById(id);
if (map1 == null || map1.get("content") == null) {
return Collections.singletonMap("subject", new ArrayList<>());
}
ObjectMapper objectMapper = new ObjectMapper();
String subject = (String) map1.get("content");
// 使用 TypeReference 指定泛型类型
Map<String, ArrayList<QuestionVo>> map2 = objectMapper.readValue(
subject,
new TypeReference<Map<String, ArrayList<QuestionVo>>>() {}
);
return map2;
} catch (JsonProcessingException e) {
throw new BussinessException("问卷调查转化异常");
}
}
java
/**
* 查询用户的问卷调查通过id Mapper
* @return
*/
@Select("select content from module_user_questionnaire where id = #{id}")
Map queryUserQuestionnaireById(@Param("id") Integer id);
以下是导出模板
XML
9、是否对中医药文化感兴趣?
A. 非常感兴趣 {{one_0}}
B.一般 {{one_1}}
C.不感兴趣 {{one_2}}
10、想通过中医药元宇宙学习到什么知识?
A. 中医药基本理论 {{two_0}}
B.中医药临床知识 {{two_1}}
C.针灸推拿技术 {{two_2}}
D.食疗养生知识 {{two_3}}
E.其他,请填写! {{two_4}} {{two_supplement}}
11、之前是否学习过中医药文化?
A.是 {{three_0}}
B.否 {{three_1}}
12、每天入睡时间是_-点,睡眠时长为_-小时
A.21:00-23:00,7-8小时 {{four_0}}
B.23:00-1:00,6-7小时 {{four_1}}
C.1:00-3:00,5-6小时 {{four_2}}
E.其他,请填写: {{four_3}} {{four_supplement}}
13、认为自己健康吗?
A. 非常健康 {{five_0}}
B.一般 {{five_1}}
C.不健康 {{five_2}}
14、对健康的期许(可多选)
A. 身体健康,不生病 {{six_0}}
B.精神健康,心情愉快 {{six_1}}
C.饮食健康,胃口好、吃饭香 {{six_2}}
D.运动健康,体能充沛 {{six_3}}
E.其他,请填写: {{six_4}} {{six_supplement}}