FreeMarker模板导出word报表

本文档详细介绍了如何使用Freemarker模板来代替easyExcel导出更复杂的Word报表。步骤包括制作XML模板,编写Java工具类,以及如何准备和调用工具类生成报表。关键步骤包括在Word中设计样式,保存为XML并用编辑器进行字段替换,以及在Java代码中设置模板路径,加载数据并生成Word文件。测试案例展示了数据映射和图片处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近遇到了生成报表操作的需求,使用easyExcel导出表格,并不能很好的满足项目需求,所以最终选择了freemarker的方式来导出word报表,网上各种各样的笔记层出不穷,所以此文用来记录自己实际应用的过程。

使用freemarker模板导出word文档大致可分为三步

  1. 制作word模板
  2. 编写生成word文档的工具类
  3. 准备数据,调用模板生成word文档

1.制作模板

1.1打开office-word,创建新的word文档,并编写自己需要的样式,例如:

 1.2编写好样式之后,另存为xml格式

 1.3用相关工具(我用的是notepad++)打开文档并格式化,修改你要填入实际数据的地方

例如:该模板是一个报表表格,有很多行,所以需要在表格前加<#List 实际数据名称 as 数据名称>标签,然后替换相关字段,此处终端一号替换为${dataList。terminalName};是因为我的数据名称为terminalName;

 注:图片则需要将那一大串base64编码(在binData标签中间)修改为相关字段:例如下图

 

也要注意图片的ID,不修改的话会所有图片都长一样!!!!!!!

1.4 完成字段替代后,保存,将文件后缀名修改为.ftl 

1.5 将文件放在项目中:例如下图


2.编写工具类

2.1导入依赖

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

2.2编写工具类

/**
 * @author Lsc
 */
@Component
public class WordUtils {
    /**
     * 生成word
     * @param dataMap
     * @throws Exception
     */
    public void saveWord(Map<String,Object> dataMap) throws Exception {
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("UTF-8");
        //模板文件所在路径,此处我将刚才生成的模板放在了resources/templates下
        configuration.setClassForTemplateLoading(this.getClass(), "/templates");
        Template template = configuration.getTemplate("report.ftl", "utf-8");
        //导出文件
        File outFile = new File(commonProperties.getWordPath() + dataMap.get("fileName") +".doc");
        Writer out = null;
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(outFile);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
            out = new BufferedWriter(outputStreamWriter);
            template.process(dataMap, out);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            out.close();
        }
    }

     /**
     * 将图片转为base64编码
     */
    public String getImgStr(String imgFile){
        //将图片文件转化为字节数组字符串,并对其进行Base64编码处理
        InputStream in = null;
        byte[] data = null;
        //读取图片字节数组
        try
        {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return new String(Base64.encodeBase64(data));
    }


}

3.准备数据,调用工具类

此处为一个测试类,实际生产中放在具体的业务中就可以了,记得字段要和模板统一!

@SpringBootTest(classes = UapApplication.class)
public class FreemarkerTest {

    @Autowired
    private WordUtils wordUtils;
    @Test
    public void test1() throws Exception {
        Map<String,Object> maps = new HashMap<>();
        maps.put("fileName","报表测试111");
        Map<String,String> map = new HashMap<>();
        map.put("terminalName","终端1号");
        map.put("terminalSn","36695sss");
        map.put("time","2021-11-11");
        map.put("result","正常");
        // 图片要转为base64编码才可以正常展示
        map.put("originalImg",wordUtils.getImgStr("C:\\Users\\DELL\\Desktop\\1.png"));
        map.put("identifyImg",wordUtils.getImgStr("C:\\Users\\DELL\\Desktop\\2.png"));
        //因为我的报表列数是根据实际数量变化的,所以这里和模板都用了列表
        List<Map<String,String>> datalist = Lists.newArrayList();
        datalist.add(map);
        datalist.add(map);
        maps.put("dataList",datalist);
        wordUtils.saveWord(maps);
    }

}

最终结果图:

SpringBoot_Freemarker生成Word_多个表格+两层嵌套循环; 步骤说明: 1.用Microsoft Office Word打开word原件;将文档中需要动态生成的内容,替换为属性名 ${name} 2.另存为,选择保存类型Word 2003 XML 文档(*.xml) 3.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容; 4. 文档生成后有时需要手动修改,查找第一步中设置的属性名,可能会产生类似${n.....ame}类似的样子,我们将将名字中间的标签删掉,恢复为${name} 5. word模板中有表格,需要循环的位置, 用 标签将第二对 标签(即除表头的w:tr标签后的一对)包围起来 同时表格内的属性例如${name},在这里需要修改为${user.name} (userList是集合在dataMap中的key, user是集合中的每个元素, 类似), 如图: PLUS:若表格之外还有嵌套的循环,也需要用,注意这里的标签不要和某对其他标签交叉,不可以出现这种 6. 标识替换完之后,另存为.ftl后缀文件即可。 代码里是相对有一丢丢复杂的,两层嵌套循环; 总(dataMap) deptName 部门名 list(Table)表的集合 table1(map) table-名字 ${map.table} tableName-中文名 ${map.tableName} columnCount-字段数 ${map.columnCount} recordCount-记录数 ${map.recordCount} listA-List--表格1 map.listA column Model属性——字段名 ${model.column} columnName Model属性——字段中文名 ${model.column} rate Model属性——字段占比 ${model.rate} nullValueCount Model属性——字段空值数 ${model.nullValueCount} listB-List--表格2 map.listB …… listC-List--表格3 map.listC …… table2 table-名字 ${map.table} tableName-中文名 ${map.tableName} columnCount-字段数 ${map.columnCount} recordCount-记录数 ${map.recordCount} listA-List--表格1 map.listA column Model属性——字段名 ${model.column} columnName Model属性——字段中文名 ${model.column} rate Model属性——字段占比 ${model.rate} nullValueCount Model属性——字段空值数 ${model.nullValueCount} listB-List--表格2 map.listB …… listC-List--表格3 map.listC …… table3 ……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值