java 创建word文件_java基于feemarker 生成word文档(超级简单)

这篇博客介绍了如何利用FreeMarker模板引擎将数据动态插入到Word文档中,详细阐述了从创建模板、转换XML到使用Java代码处理数据并导出Word的步骤。此外,还展示了如何处理列表数据和直接导出文件到浏览器。
摘要由CSDN通过智能技术生成

问题由来:

开发个新需求,需要按规定导出word文档,文档截图如下

363e8d0d99de8c56e190a197ecddd6fa.png

因为之前没做过这个,一脸懵B啊,导出excel和txt倒是经常接触到,对于这个word这种格式不严谨的文件怎么处理呢?

技术选型:可协助实现的技术很多,但是本人极力推荐feemarker,简直太好用了。

具体实施:

步骤一:maven项目 先添加如下依赖:

org.freemarker

freemarker

2.3.20

不是maven的,去下载feemarker.jar 导入就好了

步骤二:原理就是先做一个word模板, 该模板中变量数据用${xxx}这种方式填写, 然后再导出时只需读取模板然后用相应的数据替换其中的${xxx}即可.

45e9b058fc112c94ce423f3b643c0eff.png

我们这里设置了三个变量;

步骤三: 把该word文档 另存为xml文件(是另存为,不是改扩展名为xml),然后再改扩展名为ftl,步骤不能错。随便放在一个地方,我们这里先放在D盘根目录 名为 测试.ftl;

步骤四:上代码

try{

Map dataMap = new HashMap();

dataMap.put("account", "123456");

dataMap.put("name", "张三");

dataMap.put("idNumber", "123123");

Configuration configuration= newConfiguration();

configuration.setDefaultEncoding("utf-8");//指定模板路径的第二种方式,我的路径是D:/ 还有其他方式

configuration.setDirectoryForTemplateLoading(new File("D:/"));//输出文档路径及名称

File outFile = new File("D:/test.doc");//以utf-8的编码读取ftl文件

Template t = configuration.getTemplate("测试.ftl","utf-8");

Writer out= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"),10240);

t.process(dataMap, out);

out.close();

}catch(IOException e) {

e.printStackTrace();

}catch(Exception e) {

e.printStackTrace();

}

跑起来,大兄弟。

步骤四:跑完,发现在我的D盘  有个test.doc,点开看看

106af6ca450402a6851c766501720e07.png

完美啊,发现数据进去了。

技术扩展(循环列表):

其实到这里,已经可以满足很多的场景需要了。

但是我们这里还欠缺了点,因为我们的数据列表是循环的,因为可能不止一条数据。

那怎么办呢?

其实feemarker已经为我们考虑了这一点了, 先上代码

Map map1 = new HashMap();

map1.put("account", "123456");

map1.put("name", "张三");

map1.put("idNumber", "123123");

Map map2 = new HashMap();

map2.put("account", "456789");

map2.put("name", "李四");

map2.put("idNumber", "123");

List> newlist = new ArrayList<>();

newlist.add(map1);

newlist.add(map2);

Map dataMap = new HashMap<>();

dataMap.put("userList", newlist);

Configuration configuration= newConfiguration();

configuration.setDefaultEncoding("utf-8");//指定模板路径的第二种方式,我的路径是D:/ 还有其他方式

configuration.setDirectoryForTemplateLoading(new File("D:/"));//输出文档路径及名称

File outFile = new File("D:/test.doc");//以utf-8的编码读取ftl文件

Template t = configuration.getTemplate("测试.ftl","utf-8");

Writer out= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"),10240);

t.process(dataMap, out);

out.close();

代码里我们对数据的封装做了改动,我们传了list进去,list里面都是key相同的map;

还得对我们的 ftl 文件内容改动一下

搜索  w:tr 可以找到行的起点与结束点(注意第一对w:tr 是表头,应找第二对 w:tr), 如图(网上摘录的图,因为我自己的ftl文件内容太大,截不了):

d4c8ff838f87d61624df33cf58892816.png

用 #list>标签将第二对 w:tr 标签包围起来(userList是集合的key, user是集合中的每个元素, 类似), 如图:

13590f244371290e398a8548602314dc.png

当然,这里的user.a   要换  user随便写,和上面的as user对应起来就好,这里需要改成user.account, user.name,user.idNumber;

现在看看文件变成什么样了

340b9de98e92f0255eaa94de1a0ffa0b.png

完美解决list循环读取的问题;

扩展二(直接导出):

显然我们这里处理文件的方式是直接生成文件放在了D盘里,更多的时候,我们需要直接导出;

Map dataMap = getData(); //获取数据//Configuration用于读取ftl文件

Configuration configuration = newConfiguration();

configuration.setDefaultEncoding("utf-8");//获取模板所在的路径

configuration.setDirectoryForTemplateLoading(new File(pathHelper.getWebClassesPath()+"/template"));//以utf-8的编码读取ftl文件

Template t = configuration.getTemplate("测试.ftl","utf-8");

String fileName= URLEncoder.encode("客户信息-","UTF-8") + dataMap.get("formCode")+".doc";//1.设置文件ContentType类型,这样设置,会自动判断下载文件类型

response.setContentType("multipart/form-data");//2.设置文件头:最后一个参数是设置下载文件名(假如我们叫a.pdf)

response.setHeader("Content-Disposition", "attachment;fileName=" +fileName);

Writer out= new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), "utf-8"),10240);

t.process(dataMap, out);

out.close();

这样就可以直接导出了。

可能遇到的bug:

就是获取模板的那步可能会出问题,提示找不到模板。feemarker为我们提供了三种方法

第一种:基于类路径,HttpWeb包下的framemaker.ftl文件

configuration.setClassForTemplateLoading(this.getClass(), "/HttpWeb");

第二种:基于文件系统

configuration.setDirectoryForTemplateLoading(new File("/template"))

第三种:基于Servlet Context,指的是基于WebRoot下的template下的framemaker.ftl文件

HttpServletRequest request = ServletActionContext.getRequest();

configuration.setServletContextForTemplateLoading(request.getSession().getServletContext(), "/template");

因为放在项目中,肯定想设置个相对路径,我就选择了第一种,

项目存放路径

be3bdbfbe864688ac7a45aa2282c4524.png

注意:configuration.setClassForTemplateLoading(this.getClass(),"/jasperreports");

这样就可以了,千万别写什么 /resources/jasperreports,因为maven项目打包的时候,resources文件夹就不存在了。

好了到这里,介绍完毕,是不是很简单又美观呢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值