java实现word模板导出
以下文档为例
方案一 通过freemarker模板引擎
步骤
1.制作模板
使用freemark语法填充变量
另存为xml格式
使用记事本工具检查${}是否连贯,把中间的内容删除即可
在循环处增加<#list 集合名 as 变量名></#list>
将xml文件的后缀改为.ftl
2.代码实现
添加依赖
<!--freemark模板引擎-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
@RestController
@RequestMapping("/word")
public class WordExportController {
@GetMapping("/export")
public void wordExport(HttpServletResponse response) {
Map<String, Object> data = new HashMap<>();
data.put("name", "年终总结大会");
data.put("place", "第一会议室");
data.put("time", "2021年3月25日");
data.put("sponsor", "张三");
List<User> users = Lists.newArrayList(
new User("张三", "组织部", "10:00"),
new User("李四", "宣传部", "10:00"));
data.put("userList", users);
FreeMarkerUtil.createLocalDoc(data, response);
}
}
public static void createLocalDoc(Map<String, Object> data, HttpServletResponse response) {
try {
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
response.setHeader("Content-disposition", "attachment;filename=" + new String("会议签到表".getBytes("utf-8"), "ISO8859-1"));
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
configuration.setDefaultEncoding("UTF-8");
configuration.setDirectoryForTemplateLoading(new File("C:\\Users\\luban\\Desktop"));
Template template = configuration.getTemplate("test.ftl");
OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
template.process(data, writer);
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
log.info("生成word文档发生异常<{}>", e.getMessage());
}
}
3.效果如下
4.补充
以上方法导出的word文档直接用ms打开没什么问题,但是要再java中使用pdf转换还是不行,因为其本质上还是一个xml文件,所以需要结合zip文件将其转换为word对应格式
另存为mht(包含富文本必须用此格式) 或者word xml
使用这种方法对普通变量,少量图片处理基本没啥问题
需要使用远程模板参考https://blog.csdn.net/MrSpirit/article/details/100770060
word标签解析参考https://blog.csdn.net/renfufei/article/details/77481753
方案二 Xdocreport和Freemaker生成docx
只使用freemaker生成简单的word文档很容易,但是当word文档需要插入动态图片,带循环数据,且含有富文本时解决起来相对比较复杂,但是使用Xdocreport可以轻易解决。
Xdocreport既可以实现文档填充也可以实现文档转换,此处只介绍其文档填充功能。
源码地址;https://github.com/opensagres/xdocreport
文档地址:https://github.com/opensagres/xdocreport/wiki/GettingStarted
步骤:
1.制作模板
以以下文档为例
会议内容为一段富文本
我们需要在变量替换的位置通过快捷键Ctrl+F9 或 工具栏“插入”->“文档部件或文本”->“域”
选择邮件合并,添加对应属性
遇到需要循环的位置
在第一列的里
“@before-row[#list userList as user]”
@after-row[/#list]
遇到图片,先插入一张图片,再为图片添加书签
这样模板就制作完成,不需要保存为xml,ftl。直接使用doc或者docx后缀即可
2.代码实现
引入依赖
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>xdocreport</artifactId>
<version>2.0.2</version>
</dependency>
核心代码
public static void createXdocreport() {
try {
//使用远程模板
// InputStream inputStream = new URL(templateUrl).openConnection().getInputStream();
File inputPath = new File("C:\\Users\\luban\\Desktop\\summary.docx");
FileInputStream inputStream = new FileInputStream(inputPath);
File outputPath = new File("C:\\Users\\luban\\Desktop\\test.docx");
FileOutputStream outputStream = new FileOutputStream(outputPath);
IXDocReport report = XDocReportRegistry
.getRegistry()
.loadReport(inputStream, TemplateEngineKind.Freemarker);
// 设置特殊字段
FieldsMetadata metadata = report.createFieldsMetadata();
metadata.addFieldAsTextStyling("content", SyntaxKind.Html);
metadata.addFieldAsImage("avatar", "user.avatar", NullImageBehaviour.RemoveImageTemplate);
report.setFieldsMetadata(metadata);
// 创建内容-text为模版中对应都变量名称
String content = "<p>我在这里放了一段富文本</p>" +
"<p>我准备测试富文本的处理</p>";
content = HtmlUtils.htmlUnescape(content);
IContext context = report.createContext();
context.put("name", "年终总结大会");
context.put("time", "2021年3月26日");
context.put("place", "线上");
context.put("sponsor", "张三");
context.put("content", content);
//图片这里放图片的输入流
InputStream p1 = new FileInputStream(new File("C:\\Users\\luban\\Desktop\\图片1.png"));
InputStream p2 = new FileInputStream(new File("C:\\Users\\luban\\Desktop\\图片2.jpg"));
List<UserAvatar> users = Lists.newArrayList(
new UserAvatar("张三", "组织部", new ByteArrayImageProvider(p1)),
new UserAvatar("李四", "宣传部", new ByteArrayImageProvider(p2)));
context.put("userList", users);
// 生成文件
report.process(context, outputStream);
inputStream.close();
outputStream.close();
} catch (Exception e) {
log.info("生成纪要文件发生异常:<{}>", e.getMessage());
}
}
测试
public static void main(String[] args) {
createXdocreport();
}
效果如下
源码地址
https://github.com/lubanjune/word-export.git
参考博文
https://blog.csdn.net/renfufei/article/details/53283320
https://blog.csdn.net/weixin_44569204/article/details/86543711
https://blog.csdn.net/erpenggg/article/details/106714402