文章
问答
冒泡
JAVA通过freemarker实现自动填充word文档

一.需求背景

甲方提供了word格式的报告模板,我方需要通过业务系统中的数据自动把报告模板中的内容填充完整,生成一份word报告,以代替人力去系统中查找数据并手动填充word报告模板.

二.技术方案

通过freemarker模板引擎实现:

  1. 通过word文档编写出可供freemarker读取的**.ftl模板

  2. java代码引入freemarker依赖,读取**.ftl模板并将数据整理填充,通过io流输出文件

  3. 将输出的文件加工成word文档

三.具体实现

1.编写ftl模板

将客户提供的word模板解压缩,会得到以下四个文件(夹),进入word文件夹,找到document.xml.此文件即word文档中我们要编写的内容.将此文件剪切出并打开.

1-1.png

1-2.png


打开后找到我们在word文档中标记的占位符,将其使用${}包裹,即可实现模板的基本编辑.


多数情况下,我们需要对表格进行填充,这就涉及到了list循环,其实也是一样的道理,找到我们占位符的父标签,并用<#list arrayList as item><#list>标签进行包裹即可,具体如图:


2-1.png


2-2.png


同时,ftl支持if...else等多种判断,也支持字体,颜色,格式等修改 应用比较灵活


此时,一个ftl模板就做好了

2.java代码实现模板字段填充

引入freemarker依赖包

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>

实现逻辑:

package com.jscoe.core.commons.util;

import com.google.common.collect.Lists;
import com.jscoe.core.modules.ftl.entity.Drafter;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import java.io.*;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Log4j2
public class FtlUtil {
    private static final String ENCODING = "UTF-8";
    private static final String outFilePath = "E:\\****\\result\\document.xml";

    public void test() throws Exception {
        // 第一步:创建一个Configuration对象,直接new一个对象。构造方法的参数就是FreeMarker对于的版本号。
        Configuration configuration = new Configuration(new Version("2.3.23"));
        // 第二步:设置模板文件所在的路径。
        configuration.setDirectoryForTemplateLoading(new File("E:\\****"));
        // 第三步:设置模板文件使用的字符集。一般就是utf-8.
        configuration.setDefaultEncoding("utf-8");
        // 第四步:加载一个模板,创建一个模板对象。
        Template template = configuration.getTemplate("document.ftl", ENCODING);
        // 第五步:创建一个模板使用的数据集,可以是pojo也可以是map。一般是Map。
        List<Drafter> drafterArrayList = Lists.newArrayListWithCapacity(5);
        for (int i = 0; i < 5; i++) {
            drafterArrayList.add(Drafter.builder()
                    .department("总裁办"+i+"")
                    .postion("ceo"+i+"")
                    .name("老王"+i+"")
                    .sign("哈哈哈哈"+i+"")
                    .data(Instant.now()).build());
        }

        Map dataModel = new HashMap<>();
        //向数据集中添加数据
        dataModel.put("drafterList", drafterArrayList);

        // 第六步:创建一个Writer对象,一般创建一FileWriter对象,指定生成的文件名。
        Writer out = new OutputStreamWriter(new FileOutputStream(outFilePath), ENCODING);
//        StringWriter stringWriter = new StringWriter();

        // 第七步:调用模板对象的process方法输出文件。
        template.process(dataModel, out);
//        String resultStr = stringWriter.toString();
//        System.out.println(resultStr);
        // 第八步:关闭流。
        out.close();
    }
}

使用io流,将填充好的xml格式的模板放回一开始获取document.xml的地方,然后将解压得到的四个文件压缩为zip格式的压缩文件,更改格式为docx即可看到填充后的word报告.这部分功能可以借助hutool工具进行解压缩操作实现.


效果如下:


3-1.png


完美!

java
freemarker

关于作者

BenbobaBigKing
获得点赞
文章被阅读