0%

【工作技能】Word处理-FreeMarker

关于通过Java来生成word文档的代码实现,使用的技术为FreeMarker


1 动态生成Word

1.1 数据准备

  • 准备需要的数据,封装为一个Map集合
  • 例:
    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
    37
    38
    39
    40
    41
    42
    43
    44
    public class MetaData {
    //类
    public static class Person {
    public String name;
    public int age;

    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }

    public int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }

    /**
    * 获取数据
    * @return Map<String, Object>
    */
    public static Map<String, Object> getData() {
    Map<String, Object> data = new HashMap<>();

    data.put("single", "歪比巴卜");
    data.put("class", new Person("莱特雷", 18));

    List<String> arr = new ArrayList<>();
    arr.add("hello");
    arr.add("world");
    arr.add("!");
    data.put("arr", arr);

    return data;
    }
    }

1.2 根据数据创建模板

  • (1)创建word模板,用${数据名(key)},来动态获取数据
  • (2)另存为xml格式

1.3 修改xml

  • (1)格式化xml
  • 导出的xml都挤在一起,十分的难看,可以对xml进行格式化(本人使用VS Code来对xml进行格式化)
  • (2)修改xml
  • word文档转xml会将我们的${xxxx}数据进行拆分,需要我们自己合并回去
  • (3)特殊处理List集合数据
  • (4)修改后缀名为ftl
  • xml文件修改完毕后,将后缀名修改为ftl文件即可

1.4 创建Word工具类

  • (1)依赖导入
    1
    2
    3
    4
    5
    6
    <!-- FreeMarker -->
    <dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
    </dependency>
  • (2)word工具类
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    public class WordUtil {
    //编码格式
    private static final String ENCODING = "UTF-8";
    //模板路径(按自己实际情况填写)
    private static final String TEMPLATE = "/ftl/templates/word";
    //模板配置
    private static final Configuration CFG = new Configuration(Configuration.VERSION_2_3_22);


    //初始化
    static {
    //设置模板所在文件夹
    CFG.setClassForTemplateLoading(WordUtil.class, TEMPLATE);
    // setEncoding这个方法一定要设置国家及其编码,不然在ftl中的中文在生成html后会变成乱码
    CFG.setEncoding(Locale.getDefault(), ENCODING);
    // 设置异常处理器,这样的话就可以${a.b.c.d}即使没有属性也不会出错
    CFG.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
    }


    /**
    * 根据数据及模板生成word文件写入输出流
    * @param data Map的数据结果集
    * @param templateFileName ftl模版文件名
    * @param outputStream 生成文件名称(可带路径)
    */
    public static void create(Map<String, Object> data, String templateFileName, OutputStream outputStream) throws Exception {
    //获取自定义ftl模板
    Template template = CFG.getTemplate(templateFileName, ENCODING);

    //封装输出流
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);

    //动态生成word,写入输出流
    template.process(data, outputStreamWriter);
    }


    /**
    * 设置response为下载word文件格式
    * @param response 响应
    * @param fileName 文件名
    */
    // public static void setWordResponse(HttpServletResponse response, String fileName) throws Exception{
    // //设置response格式
    // response.setCharacterEncoding(ENCODING);
    // response.setContentType("application/msword");
    // fileName = URLEncoder.encode(fileName, "UTF-8"); // 防止中文乱码
    // response.setHeader("content-disposition", "attachment;filename=" + fileName + ".doc");
    // }
    }
  • (3)测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Test
    public void wordTest() throws Exception{
    //模板名
    String ftlName = "wordTemplate.ftl";
    //导出word路径
    String outputFile = "./src/main/resources/my.doc";

    //数据
    Map<String, Object> data = MetaData.getData();
    //输出流
    OutputStream outputStream = new FileOutputStream(outputFile);

    //调用工具类生成word文档
    WordUtil.create(data, ftlName, outputStream);
    }