您的位置:首页 > 运维架构

word的xml 转换为 docx

2018-02-02 10:21 176 查看
本文转自:::http://hucheng91.github.io/2017/04/09/web/java/freemarker_xdocxreport/

//================================转者附注释=====================================

最近有个问题是,通过freemarker生成的word出现了问题,因为是先把word转换为xml作为模板填充的文件,所以生成的doc的底层还是xml格式的,openoffice转换为的pdf出现了pdf中全是xml格式的问题,后面经过发现了下面这篇博文,完美的解决了我们的问题。

注:我们使用的openoffice,没有使用xdoxreport。这个性能不是很好。所以下面删除了有关xdoxreport的内容

//================================结束==========================================

最近公司有个业务,是要生成pdf形式的合约,合约模版是有十几页的word,根据不同的客户,模版有些地方填入不同的值,然后生成pdf格式的合约。最开始打算用JasperReports,先把这个模版画出来,但是由于模版页数太多,样式很复杂,JasperReports处理起来简直就是噩梦,果断放弃,随后我又调研了doc4j,openoffice;doc4j处理复杂文档也不是太好,加粗的字体都没有显示出来,对office2013不怎么支持,openoffice得单独装一个服务端,很是耗资源,也放弃了;最后我选择了先用freemarker将模版变量填入生成一个docx,在用xdocreport这个库来将docx转换成pdf,成功的实现了,支持office的2007,2013等,而且docx样式也完全保留下来,而且整个过程非常快,不怎么耗费资源,内存;

先介绍下freemarke
freemarker是java里一个模版框架,和velocity类似,不仅支持各种xml格式,freemarker地址



然后介绍下我整体的一个思路,MS-Office下的word在2007以后后缀基本是以.docx结尾,是用一种xml格式的在存储数据(.doc是用二进制存储数据),这就为使用freemarker提供的条件,如果把template.docx,重命名成template.zip,再用word一样是可以打开的,如果有WinRAR之类的压缩工具打开会发现如下目录结构


我们用office工具打开看到的内容其事就存放在在这个document.xml里面!,打开看看(document.xml默认是不换行的,我用Nodpad++打开,然后下载nodpad插件Xml-tool格式化后,具体安装可参考Nodepad
格式化xml)在这个xml就是以这种格式存储的数据,只需要将我们需要的内容变成一个变量,然后通过freemarker来解析这xml,让后用解析后的xml,把template.zip里面的document.xml替换掉,然后将这个template.zip解压成data.docx,那么这个data.docx,就包含了我们需要的数



具体操作如下
处理模版对应的docx


将test.docx重命名test.zip,将document.xml copy 出来 ,打开 document.xml,


java代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

/** 初始化配置文件 **/
Configuration
configuration = new Configuration();
/** 设置编码 **/
/** 我的ftl文件是放在D盘的**/
String fileDirectory = "D:/cache/qqChace/T1/xlsx";
/** 加载文件 **/
configuration.setDirectoryForTemplateLoading(new File(fileDirectory));
/** 加载模板 **/
Template template = configuration.getTemplate("document.xml");
/** 准备数据 **/
Map<String,String> dataMap = new HashMap<>();
/** 在ftl文件中有${textDeal}这个标签**/

dataMap.put("id","黄浦江吴彦祖");
dataMap.put("number","20");
dataMap.put("language","java,php,python,c++.......");
dataMap.put("example","Hello World!");

/** 指定输出word文件的路径 **/
String outFilePath = "D:/cache/qqChace/T1/xlsx/data.xml";
File docFile = new File(outFilePath);
FileOutputStream fos = new FileOutputStream(docFile);
OutputStreamWriter oWriter = new OutputStreamWriter(fos);
Writer out = new BufferedWriter(new OutputStreamWriter(fos),10240);
template.process(dataMap,out);

if(out != null){
out.close();
}
// ZipUtils 是一个工具类,主要用来替换具体可以看github工程
ZipInputStream zipInputStream = ZipUtils.wrapZipInputStream(new FileInputStream(new File("D:/cache/qqChace/T1/xlsx/test.zip")));
ZipOutputStream zipOutputStream = ZipUtils.wrapZipOutputStream(new FileOutputStream(new File("D:/cache/qqChace/T1/xlsx/test.docx")));
String itemname = "word/document.xml";
ZipUtils.replaceItem(zipInputStream, zipOutputStream, itemname, new FileInputStream(new File("D:/cache/qqChace/T1/xlsx/data.xml")));
System.out.println("success");

生成test.docx如下

,这样我通过freeemark生成docx这件事就搞定了


把整个打包成一个工程
,放到github上https://github.com/hucheng91/freemarker_xdoxreport.git

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息