Java使用freemarker导出docx(WPS、OFFICE都可以看!)

继上篇导出一个完美的doc后,业务又发生了变化必须生成docx格式的word才行(哭泣)。
但是利用freemarker生成的word文档(doc/docx)利用notepad++打开是xml格式。而正常的文档格式利用notepad打开是乱码。很明显,就算你废了九牛二虎之力导出来的word OFFICE也绝对打开不了(WPS作为小可爱确可以打开= =)。
例如下图:
在这里插入图片描述
目前你生成的doc/docx底层还是xml格式的,转pdf或者在手机上看都只能看到xml文件。

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,就包含了我们需要的数据
来源:https://blog.csdn.net/u013076044/article/details/79236000

上面这段话我翻看了近100篇博客才找到。。真的是受益匪浅
导入步骤如下:

  1. 处理模版对应的docx,和我上篇一样替换变量就好啦。(插入图片的话,见这篇博客https://blog.csdn.net/SOME___ONE/article/details/52562743)
  2. 将你的docx文件重命名x.zip,用压缩包工具打开它。将word/document.xml copy出来!
    在这里插入图片描述

document.xml文件用于存放核心数据,文字,表格,图片引用等
media目录用于存放所有文档的图片
_rels目录下的document.xml.rels里存放的是配置信息,比如图片引用关系,即在document.xml中引用id对应media中的哪个图片。
获取zip里的document.xml文档以及_rels文件夹下的document.xml.rels文档
显而易见,如果我们要想根据数据动态导出不同的word文档,只需要:通过freemarker将本次数据填充到document.xml中,并将图片配置信息填充至document.xml.rels文档里,再用文件流把本次图片写入到media目录下替换已经存在的图片,最后把填充过内容的document.xml、document.xml.rels以及media用流的方式写入zip即可输出docx文档!

  1. 写代码~
@Test
    public void ttt() throws Exception {
   
        /** 初始化配置文件 **/
        Configuration configuration = new Configuration();
        /** 设置编码 **/
        /** 我的ftl文件是放在D盘的**/
        String fileDirectory = "G:\\work_code";
        /** 加载文件 **/
        configuration.setDirectoryForTemplateLoading(new File(fileDirectory));
        /** 加载模板 **/
        Template template = configuration.getTemplate("document.xml");

        /** 准备数据,这里是我自己的业务。就是把变量赋值上${xxxx}去啦 **/
        Map<String,String> dataMap = detailService.showWordDetail();
 

        /** 指定输出word文件的路径 **/
        String outFilePath = "G:\\work_code\\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();
        }
        ZipInputStream zipInputStream = ZipUtils.wrapZipInputStream(new FileInputStream(new File("G:\\work_code\\1.zip")));
        ZipOutputStream zipOutputStream = ZipUtils.wrapZipOutputStream(new FileOutputStream(new File("G:\\work_code\\test.docx")));
        String itemname = "word/document.xml";
        ZipUtils.replaceItem(zipInputStream, zipOutputStream, itemname, new FileInputStream(new File("G:\\work_code\\data.xml")));
        System.out.println(
  • 15
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值