FreeMarker导出word或excel文件实践

目录

      • 准备操作实践环境
      • 报表模板设计
      • 导出word格式报表
      • 增加报表模板变量的再导出
      • 总结

Apache FreeMarker 是一个基于 Java 的报表引擎,之前听说过它可以生成 HTML 网页、源代码(代码生成器)等,但是使用 FreeMarker 导出 wordexcel 文件却没有尝试过,不知道其中的可行性如何,不了解其中的大概操作流程怎样,遂有了此文。

准备操作实践环境

这里以一个新建的 springboot 项目作为操作实践环境

导入 FreeMarker 的依赖


	org.springframework.boot
	spring-boot-starter-freemarker

报表模板设计

导出 wordexcel 文件可以看成导出 word 格式 或 excel 格式的报表

  1. 使用 word 编辑软件(如 WPS Office 等)设计报表,下图所示为将要导出的 word 文件样例
    FreeMarker导出word或excel文件实践_第1张图片

  2. 将上一步操作完成的 word 文件样例另存为 xml 文件

    注意:不能直接修改文件的后缀名为 xml ,那样是无效的。修改文件后缀名不影响文件本身的内容。

FreeMarker导出word或excel文件实践_第2张图片
3. 将 xml 文件的后缀名修改为 ftl

虽然这一步可以省略(因为修改文件后缀名不影响文件本身的内容),但是还是强烈建议将文件后缀名修改为 ftl ,这样能达到“见名知义”的效果,那样工作协作效率能高许多。

导出word格式报表

项目大体结构如下图所示,新建了一个 FreeMarkerTestJava 类,报表文件放在 resources 目录下的 templates
FreeMarker导出word或excel文件实践_第3张图片
其中 FreeMarkerTest 类里边创建了一个 main 方法用来导出 word 文件

package com.example.demo;

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

public class FreeMarkerTest {
    public static void main(String[] args) throws Exception {
        // 1. FreeMarker 初始化配置
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_26);
        configuration.setDefaultEncoding("UTF-8");
        configuration.setClassForTemplateLoading(FreeMarkerTest.class, "/templates/");

        // 2. 获取模板
        Template template = configuration.getTemplate("myReport.ftl");

        // 3. 准备模板数据
        Map<String, Object> dataMap = new HashMap<>();

        // 4. 导出文件
        File outFile = new File("C:/Users/ligs/Desktop/word测试.docx");
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
        template.process(dataMap, writer);
        writer.flush();
        writer.close();

        System.out.println("导出文件完毕...");
    }
}

执行上面的 main 方法,成功导出的 word 文件如下图所示。至此,可见使用 FreeMarker 报表引擎导出 word 文件是基本可行的。但是还有一个问题,目前导出的文件是静态的,它相当于原模板的一份拷贝,还无法做到根据具体数据进行动态填充报表文件。关于这个问题,继续往下探讨。
FreeMarker导出word或excel文件实践_第4张图片

增加报表模板变量的再导出

使用 word 编辑软件打开 ftl 报表模板文件,将报表需动态改变的内容调整为占位符,占位符以 ${...} 这种变量形式表示。

${...}FreeMarker Template Language(FTL) 的语法,具体可以参考官网 https://freemarker.apache.org/docs/ref.html

FreeMarker导出word或excel文件实践_第5张图片
调整程序,设置相应模板数据

// 3. 准备模板数据
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("reportTitle", "用户"); // 报告标题
dataMap.put("reporter", "admin"); // 报告人
dataMap.put("userName", "李四"); // 用户
dataMap.put("remark", "remark test"); // 备注

FreeMarker导出word或excel文件实践_第6张图片
重新执行 FreeMarkerTestmain 方法,导出的 word 文件如下图所示。
FreeMarker导出word或excel文件实践_第7张图片

总结

  1. 使用 FreeMarker 导出 word 文件是可行的。excel 文件类似,只是报表模板设计及调整报表模板变量时需对应使用 excel 编辑软件(注意不能混用,比如 ftl 模板文件是由 word 编辑软件设计转换而来的,那么调整报表模板变量或对模板进行调整设计时,也要使用 word 编辑软件来调整。否则,报表模板无法正常显示,只是显示出一些文本内容)。
  2. 使用 FreeMarker 导出 word / excel 文件的大致流程:设计报表模板原型 => 调整报表模板变量 => 程序设置模板数据并导出。(在这个过程中,wordexcel 编辑软件既充当了报表设计工具,又充当了报表文件的查看工具)
  3. 文中的 FreeMarkerTest Java 类里边的代码只是为了快速进行技术验证,在实际项目中不能直接这样使用,其中还有许多要点需要注意:
    // 代码省略...
    public class FreeMarkerTest {
    	// 要点1:实际项目中,FreeMarker 导出文件可能需要单独整理出来一个工具类
        public static void main(String[] args) throws Exception {
            // 1. FreeMarker 初始化配置
            // 代码省略...
            // 要点2:根据 FreeMarker 官网(https://freemarker.apache.org/)的介绍,FreeMarker 的配置实例应该仅初始化一次,
            // 比如仅在应用程序启动时初始化,后续整个应用程序都共用一个相同的 Configuration 
            Configuration configuration = ...;
    
            // 2. 获取模板
            Template template = configuration.getTemplate("xx.ftl");
    
            // 3. 准备模板数据
            Map<String, Object> dataMap = new HashMap<>();
            // 代码省略...
            // 要点3:模板数据可以是一个 map 类型,也可以是一个带 get/set 方法的 JavaBean,等等
    
            // 4. 导出文件
            // 代码省略...
            File outFile = new File("xx.docx"); // 要点4:如果 ftl 模板原先由 excel 编辑软件设计的,这里应该导出 excel 格式(如 *.xlsx),保持一致,达到“见名知义”的效果
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            template.process(dataMap, writer);
            writer.flush();
            writer.close(); // 要点5:资源的回收应该确保一定会得到执行,比如相应操作放在 try...catch...finally 中的 finally 块中。
            
        }
    }
    
    

你可能感兴趣的:(后端开发,spring,boot,freemarker)