Freemarker + xml 实现Java导出word
前言
最近做了一个调查问卷导出的功能,需求是将维护的题目,答案,导出成word,参考了几种方案之后,选择功能强大的freemarker+固定格式之后的wordxml实现导出功能。导出word的代码是可以直接复用的,于是在此贴出,并进行总结,方便大家拿走。
实现过程概览
先在word上,调整好自己想要的样子。然后存为xml文件。保存为freemarker模板,以ftl后缀结尾。将需要替换的变量使用freemarker的语法进行替换。最终将数据准备好,和模板进行渲染,生成文件并返回给浏览器流。
详细的实现过程
准备好word的样式
我们新建一个word,我们应该使用Microsoft office,如果使用wps可能会造成样式有些不兼容。在新建的office中,设置好我们的表格样式。我们的调查问卷涉及到四种类型,单选,多选,填空,简答。我们做出四种类型的示例。

样式没有问题后,我们选择另存为word xml 2003版本。将会生成一个xml文件。

格式化xml,并用freemarker语法替换xml
我们可以先下载一个工具 firstobject xml editor,这个可以帮助我们查看xml,同时方便我们定位我们需要改的位置。
复制过去之后,按f8可以将其进行格式化,左侧是标签,右侧是内容,我们只需要关注w:body即可。

像右侧的调查问卷这个就是个标题,我们实际渲染的时候应该将其进行替换,比如我们的程序数据map中,有title属性,我们想要这里展示,我们就使用语法${title}即可。

freemarker的具体语法,可以参考freemarker的问题,在这里我给出几个简单的例子。
比如我们将所有的数据放置在dataList中,所以我们需要判断,dataList是不是空,是空,我们不应该进行下面的逻辑,不是空,我们应该先循环题目是必须的,答案是需要根据类型进行再次循环的。语法参考文档,这里不再赘述。
程序端引入freemarker
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
将我们的flt文件放在resources下的templates下。
后端代码实现
此代码可以复用,在此贴出
public class WordUtils {
private static Configuration configuration = null;
private static final String templateFolder = WordUtils.class.getClassLoader().getResource("").getPath()+"/templates/word";
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
try {
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @Description:导出word,传入request,response,map就是值,title是导出问卷名,ftl是你要使用的模板名
*/
public static void exportWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws Exception {
Template freemarkerTemplate = configuration.getTemplate(ftlFile);
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
file = createDocFile(map,freemarkerTemplate);
fin = new FileInputStream(file);
String fileName = title + ".doc";
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
response.setHeader("Content-Disposition", "attachment;filename="
+fileName);
out = response.getOutputStream();
byte[] buffer = new byte[512];
int bytesToRead = -1;
while((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
}finally {
if(fin != null) fin.close();
if(out != null) out.close();
if(file != null) file.delete();
}
}
/**
* @Description:创建doc文件
*/
private static File createDocFile(Map<?, ?> dataMap, Template template) {
File file = new File("init.doc");
try {
Writer writer = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
template.process(dataMap, writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
}
有了工具类后,我们准备好我们的map数据。map里面的数据大家可以自行定义。然后调用utils中的导出方法即可。
WordUtils.exportWord(request, response, dataMap, "word", "demo.ftl");
结语
至此已经结束了,十分的好用,有疑问的话,可以评论交流。
Freemarker + xml 实现Java导出word的更多相关文章
- java导出word的6种方式(复制来的文章)
来自: http://www.cnblogs.com/lcngu/p/5247179.html 最近做的项目,需要将一些信息导出到word中.在网上找了好多解决方案,现在将这几天的总结分享一下. 目前 ...
- java导出word文件
java导出word文件 test5.ftl文件生存方法, 第一步:用word新建test5.doc,填写完整模板,将需导出数据用${}代替 第二步:将test5.doc另存为test5.xml 第三 ...
- [转载]java导出word的5种方式
在网上找了好多天将数据库中信息导出到word中的解决方案,现在将这几天的总结分享一下.总的来说,java导出word大致有5种解决方案: 1:Jacob是Java-COM Bridge的缩写,它在Ja ...
- [原创]java导出word的5种方式
在网上找了好多天将数据库中信息导出到word中的解决方案,现在将这几天的总结分享一下.总的来说,java导出word大致有5种解决方案: 1:Jacob是Java-COM Bridge的缩写,它在Ja ...
- java导出word的6种方式(转发)
来自: http://www.cnblogs.com/lcngu/p/5247179.html 最近做的项目,需要将一些信息导出到word中.在网上找了好多解决方案,现在将这几天的总结分享一下. 目前 ...
- java对word文档的操作(提取标题和内容等)-直接操作或poi工具包或freemarker+xml或html转word
1,java自带工具包实现对word的排版和写入 import java.awt.Color; import java.io.FileNotFoundException; import java.io ...
- java导出word直接下载
导出word工具类 package util; import java.io.IOException; import java.io.Writer; import java.util.Map; imp ...
- WordUtil java导出word工具类
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedWriter ...
- java 导出word 并下载
记录一下导出操作 源码: /************ * 导出word 并下载 * @param id 房号记录编号 * ***********************/ @RequestMappin ...
随机推荐
- 记因git规范导致的提测和发布延迟
号外 最近因为换工作的原因,我的博客和Github没有像之前那样频繁的更新了.一方面原因是投递简历和准备面试,由于之前的基础没有很扎实,需要把平时的知识点都整理一遍.这个时间段持续了20多天的样子,因 ...
- Leetcode(1)两数之和
Leetcode(1)两数之和 [题目表述]: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标.你可以假设每种输入只会对应一 ...
- JVM学习记录2--垃圾回收算法
首先要明确,垃圾回收管理jvm的堆内存,方法区是堆内存的一部分,所以也是. 而本地方法栈,虚拟机栈,程序计数器随着线程开始而产生,线程的结束而消亡,是不需要垃圾回收的. 1. 判断对象是否可以被回收 ...
- (day29) 进程互斥锁 + 线程
目录 进程互斥锁 队列和堆栈 进程间通信(IPC) 生产者和消费者模型 线程 什么是线程 为什么使用线程 怎么开启线程 线程对象的属性 线程互斥锁 进程互斥锁 进程间数据不共享,但是共享同一套文件系统 ...
- 设计模式C++描述----17.备忘录(Memento)模式
一. 备忘录模式 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 结构图: 使用范围: Memento 模式比较适用于功能 ...
- Bran的内核开发教程(bkerndev)-07 中断描述符表(IDT)
中断描述符表(IDT) 中断描述符表(IDT)用于告诉处理器调用哪个中断服务程序(ISR)来处理异常或汇编中的"int"指令.每当设备完成请求并需要服务事, 中断请求也会调用I ...
- 不需要怎么修改配置的Mybatis整合Spring要点
首先对于Mybatis的主配置文件,只需要修改一处地方,将事务交给Spring管理,其它地方可以原封不动. <?xml version="1.0" encoding=&quo ...
- Codeforces Round #595 (Div. 3)D1D2 贪心 STL
一道用STL的贪心,正好可以用来学习使用STL库 题目大意:给出n条可以内含,相交,分离的线段,如果重叠条数超过k次则为坏点,n,k<2e5 所以我们贪心的想我们从左往右遍历,如果重合部分条数超 ...
- 还不会用FindBugs?你的代码质量很可能令人堪忧
前言 项目中代码质量,往往需要比较有经验的程序员的审查来保证.但是随着项目越来越大,代码审查会变得越来越复杂,需要耗费越来越多的人力.而且程序员的经验和精力都是有限的,能审查出问题必定有限.而在对代码 ...
- 利用AXI VDMA实现OV5640摄像头采集笔记(二)
导读:摄像头采样图像数据后经过VDMA进入DDR,通过PS部分控制,经过三级缓存,将DDR中保持的图形数据通过VDMA发送出去.在FPGA的接收端口产生VID OUT时序驱动HDMI显示器显示图形. ...