导出word模板并动态渲染数据
一、需求介绍
背景:需要导出word模板的时候,有些数据是动态或者图片等不确定因素的时候、根据需求定制好的模板要求填充数据,那么这个时候就需要进行根据word模板进行动态添加数据渲染出 word。
本文主要介绍:
1、SpringBoot导出word模板
2、SpringBoot导出word模板并且渲染动态数据
3、SpringBoot导出word模板包含list数据循环输出
4、SpringBoot导出word模板包含图片信息展示
二、依赖添加
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
三、制作模板
制作模板思路:
1、使用word2007或者WPS进行将模板除数据外的格式进行绘制出
2、使用templeat语法将需要动态数据的位置进行替换
3、另存为制作好的word文件为xml(word 2007xml)格式的文件
4、将生成好得到xml文件修改后缀名为.ftl文件并进行代码格式化
5、检查ftl文件中是否有格式错误信息并且设置循环列表的补充、完成图片信息base64的替换
这里图片信息暂放一张图占位(后续会改)
将base64码替换成占位符
检查每一处占位符是否都正确,可能再转化后少括号或者 $ 之类的,正常补充添加调整后即可
完成对循环数组的代码补充
转成xml后找到固定的规律就是
<w:tr> </w:tr> :代表表格中的一行
<w:tc> </w:tc> :代表表格中的一个单元格
那么就需要在动态循环的地方进行添加list循环代码
这个的所有语法就是 framework 语法一样了。
以上就是模板制作的全过程。下面实现代码部分。
四、后端代码
package com.hebiyusheng.auxililaryreport.controller;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Encoder;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("studentWord")
public class ReportController {
@GetMapping("word")
public HttpServletResponse word(HttpServletResponse response) throws Exception {
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDefaultEncoding("utf-8");
String fileDirectory = "D:\\Spring\\ismy-project\\auxiliary\\auxiliary-report\\src\\main\\resources\\template\\";
configuration.setDirectoryForTemplateLoading(new File(fileDirectory));
Template template = configuration.getTemplate("student.ftl");
List<Map<String, Object>> itemList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Map<String, Object> kemu = new HashMap<>();
kemu.put("name","科目"+i);
kemu.put("chengji",90+i);
itemList.add(kemu);
}
Map<String, Object> mapList = new HashMap<>();
mapList.put("serialNo", "20220629");
mapList.put("name", "XX一中");
mapList.put("pic", getImgFileToBase64("C:\\Users\\hebiy\\Desktop\\XXXX.jpg"));
mapList.put("itemList", itemList);
mapList.put("toloclass", "700");
String outFilePath = "D:\\Spring\\ismy-project\\auxiliary\\auxiliary-report\\src\\main\\resources\\template\\" +(System.currentTimeMillis()) + ".doc";
File docFile = new File(outFilePath);
FileOutputStream fos = new FileOutputStream(docFile);
Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
template.process(mapList, out);
File file = new File(outFilePath);
String filename = file.getName();
InputStream fis = new BufferedInputStream(new FileInputStream(outFilePath));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
response.reset();
response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
toClient.close();
if (out != null) {
out.close();
}
System.out.println("下载完成......");
return null;
}
public static String getImgFileToBase64(String imgFile) {
InputStream inputStream = null;
byte[] buffer = null;
try {
inputStream = new FileInputStream(imgFile);
int count = 0;
while (count == 0) {
count = inputStream.available();
}
buffer = new byte[count];
inputStream.read(buffer);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return new BASE64Encoder().encode(buffer);
}
}
五、效果展示
说明:代码补充可自行优化。数据部分可优化为数据库读取数据等,针对部署linux问题将读取配置文件和图片信息替换成linux支持格式即可。
|