1、添加必要依赖
<!-- 需要的依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!-- word模板动态生成word poi-tl -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.8.2</version>
</dependency>
2、编写word模板
3、编写Controller
/**
* 生成 对应审查清单id的 word版
* @param listId
* @return
* @throws IOException
*/
@PostMapping("/create/{listId}")
@RequiresAuthentication
public void exportData(@PathVariable Long listId, HttpServletResponse response) throws IOException{
try {
// 根据 审查清单id 查询所包含的审查主题
List<ReviewLists> themeList = reviewListsService.selectThemeByListId(listId);
//存储所有的审查主题表
List<Map<String,Object>> lists=new ArrayList<Map<String,Object>>();
// 存储所有的审查主题表名称
List<Map<String,Object>> themeTypes=new ArrayList<Map<String,Object>>();
// 根据 主题id 获取对应的审查项
for (ReviewLists theme:themeList){
//存储当前主题表名称
Map<String,Object> themeMap = new HashMap<String, Object>();
themeMap.put("theme_type",theme.getName());
themeTypes.add(themeMap);
// 获取当前主题下的 所有审查项
List<ReviewListsItems> items = reviewListsItemsService.queryByPid(theme.getId());
//存储当前审查主题下 所有的审查项
List<Map<String,Object>> detailList=new ArrayList<Map<String,Object>>();
for (ReviewListsItems item:items){
Map<String,Object> itemMap = new HashMap<String, Object>();
itemMap.put("num",item.getItemNum());
//内容在前端存储时换行 转换为 word中换行
item.setContent(item.getContent().replaceAll("<br>","\n"));
itemMap.put("content",item.getContent());
detailList.add(itemMap);
}
// 当前主题表 以及 对应的所有审查项
Map<String,Object> listMap = new HashMap<String, Object>();
listMap.put("theme_type",theme.getName());
listMap.put("detailList",detailList);
lists.add(listMap);
}
// 获取模板路径,ClassPathResource对应的是"项目名/target/classes"
ClassPathResource classPathResource = new ClassPathResource("/templates/ReviewListModel1.docx");
String resource = classPathResource.getAbsolutePath();
//渲染表格
HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
Configure config = Configure.newBuilder()
.bind("detailList", policy)
.bind("themeTypes", policy)
.build();
XWPFTemplate template = XWPFTemplate.compile(resource, config).render(
new HashMap<String, Object>() {{
put("themeTypes", themeTypes);
put("themeList",lists);
}}
);
//=================生成文件保存在本地D盘某目录下=================
String temDir="G:/word/"; ;//生成临时文件存放地址
//生成文件名
ReviewLists list = reviewListsService.getOne(new QueryWrapper<ReviewLists>().eq("id",listId));
//用当前时间区分word
Date date = new Date();
SimpleDateFormat outDate = new SimpleDateFormat("yyyy-MM-dd-HH:mm");
String time = outDate.format(date);
//截取 时:分
String index = time.substring(11);
String listName = list.getName() + index;
// 生成的word格式,文件后缀
String formatSuffix = ".docx";
// 拼接后的文件名
String fileName = listName + formatSuffix;//文件名 带后缀
// 输出到 指定的路径
FileOutputStream fos = new FileOutputStream(temDir+fileName);
// 开始输出到本地设置的存储位置
template.write(fos);
/* 这是复制别的博主的,但是谷歌浏览器未弹出保存地址框,应该要设置一下
//=================生成word到设置浏览器默认下载地址=================
// 设置强制下载不打开
response.setContentType("application/x-msdownload");
// 设置文件名
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
OutputStream out = response.getOutputStream();
template.write(out);
out.flush();
out.close();*/
template.close();
} catch (Exception e) {
e.printStackTrace();
}
}
4、结果输出
5、遇到渲染不出的问题
就是表头的{{detailList}},必须要带上,而且对应controller中" .bind("detailList", policy) "