使用freemarker生成带表格及图片的word,循环多表格及多图片

ftl模板创建

使用word软件创建带图片和表格的doc

在这里插入图片描述

注意:这里表格中的值暂时不要写成 形式,防止保存模板为 x m l 格式后,解析出错,等到保存为 x m l 格式后,在 x m l 文件中替换成 {}形式,防止保存模板为xml格式后,解析出错,等到保存为xml格式后,在xml文件中替换成 形式,防止保存模板为xml格式后,解析出错,等到保存为xml格式后,在xml文件中替换成{}形式即可。

将word模板转换为xml格式

在这里插入图片描述

使用在线工具格式化xml,方便查看xml

https://www.bejson.com/

处理表格

在xml中找到你填入表格中的值,将值替换成${}形式,如下图:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

处理图片

如果是单张图片

直接搜索<pkg:binaryData>标签,将其中的base64图片编码替换成${img}
在这里插入图片描述
在这里插入图片描述

注意,创建word文件时,建议先不要放大图片,否则base64编码会很长,不好替换

如果是多张图片,比较麻烦点,需要替换三个地方

1. <pkg:binaryData>标签中的base64编码替换

在这里插入图片描述

2. Relationship标签,xml文件中搜索relationships/image

在这里插入图片描述

注意:此处的Target属性值要和<pkg:binaryData>标签中pkg:name属性值中的图片名称一致;

3. 搜索关键词<v:imagedata

在这里插入图片描述

注意,此处的r:id属性值要和Relationship标签中的Rid属性值一致;

这里多张图片是会横向排列在一起的,想要换行需要使用<w:p w:rsidR="00A82B52" w:rsidRPr="00CB725B" w:rsidRDefault="00CC1725" w:rsidP="00CB725B"><w:pPr><w:pStyle w:val="a5"/></w:pPr></w:p>

图片尺寸设置

在这里插入图片描述

此处图片单位为pt,可以在代码中获取到图片的宽高之后,这里使用${width}${height}替换即可。

搞完之后,将xml文件后缀改为ftl

后端代码(这里暂时没做文件下载,只是生成到指定文件夹,想要做成文件下载可以自己修改)

注意:我这里的需求是循环创建表格和图片

package com.cmx.freemarker;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.*;

/**
 * 使用Freemarker自动生成Word文档
 *
 * @author CMX
 * @version 1.2.1
 * @date 2024-05-24
 **/
public class WordGenerateUtils {

    /**
     * 使用Freemarker自动生成Word文档
     *
     * @param dataMap      保存Word文档中所需要的数据
     * @param templatePath 模板文件的绝对路径
     * @param templateFile 模板文件的名称
     * @param generateFile 生成文件的路径+名称
     */
    public static void generateWord(Map<String, Object> dataMap, String templatePath, String templateFile, String generateFile) {
        // 设置FreeMarker的版本
        Configuration configuration = new Configuration(new Version("2.3.7"));
        // 设置Freemarker的编码格式
        configuration.setDefaultEncoding("UTF-8");
        Writer out = null;
        try {
            // 设置FreeMarker生成Word文档所需要的模板的路径
            configuration.setDirectoryForTemplateLoading(new File(templatePath));
            // 设置FreeMarker生成Word文档所需要的模板名称
            Template t = configuration.getTemplate(templateFile, "UTF-8");
            // 创建一个Word文档的输出流
            File file = new File(generateFile);
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8));
            //FreeMarker使用Word模板和数据生成Word文档
            t.process(dataMap, out);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (out != null) {
            try {
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        //获取导出文件路径
        //获取当前项目resource绝对路径
        String resourcePath = getResourcePath();
        String resourceGenerateFileName = resourcePath + "\\word\\生成word.docx";

        //获取模板文件的绝对路径
        //注意:通过ClassLoader获取模板文件的绝对路径,获取的是target目录下的template文件夹下的文件,不是src目录下的template文件夹下的文件
        ClassLoader classLoader = WordGenerateUtils.class.getClassLoader();
        URL resource = classLoader.getResource("template/带表格图片freemarker模板.ftl");
        assert resource != null;
        String path = resource.getPath();
        String templatePath = path.substring(0, path.lastIndexOf("/"));
        String templateFile = "带表格图片freemarker模板.ftl";

        generateWord(getTextData(), templatePath, templateFile, resourceGenerateFileName);

    }

    private static Map<String, Object> getTextData() {
        /*
         * 创建一个Map对象,将Word文档需要的数据都保存到该Map对象中
         */
        List<Map<String, Object>> dataList = new ArrayList<>();
        String imgPath = WordGenerateUtils.class.getClassLoader().getResource("image/3.jpg").getPath();
        String imageBase64 = getImageBase64(imgPath);
        Map<String, Object> dataMap1 = new HashMap<>();
        dataMap1.put("name", "卢本伟");
        dataMap1.put("age", "20");
        dataMap1.put("img", imageBase64);
        dataMap1.put("imageName", "img1");
        dataMap1.put("title", "5.1 表格1");

        Map<String, Object> dataMap2 = new HashMap<>();
        dataMap2.put("name", "pdd");
        dataMap2.put("age", "20");
        dataMap2.put("img", imageBase64);
        dataMap2.put("imageName", "img2");
        dataMap2.put("title", "5.1 表格2");
        dataList.add(dataMap1);
        dataList.add(dataMap2);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("dataList", dataList);
        return resultMap;
    }

    public static String getImageBase64(String imagePath) {
        try (InputStream inputStream = new FileInputStream(imagePath)) {
            byte[] imageBytes = toByteArray(inputStream);
            return Base64.getEncoder().encodeToString(imageBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static byte[] toByteArray(InputStream inputStream) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        int nRead;
        byte[] data = new byte[1024];
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        buffer.flush();
        return buffer.toByteArray();
    }

    public static String getResourcePath() {
        // 获取当前项目的根目录
        String projectRootPath = Paths.get(System.getProperty("user.dir")).toAbsolutePath().toString();

        //这里获取到的根目录是项目目录,也就是others目录,子模块other需要手动加上
        return Paths.get(projectRootPath, "other", "src", "main", "resources").toString();
    }
}

注意我项目结构(有父模块和子模块)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
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 ……
### 回答1: 使用Freemarker动态生成HTML表格,您可以按照以下步骤: 1. 导入Freemarker依赖 如果您正在使用Maven或Gradle等构建工具,可以将Freemarker添加到项目的依赖中。以下是Maven的依赖: ``` <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.31</version> </dependency> ``` 2. 创建模板文件 在模板文件中,您可以使用Freemarker的语法来定义HTML表格的结构和样式。例如,以下是一个简单的模板文件,它定义了一个包含表头和表格数据的HTML表格: ``` <table> <thead> <tr> <th>Name</th> <th>Age</th> <th>Email</th> </tr> </thead> <tbody> <#list users as user> <tr> <td>${user.name}</td> <td>${user.age}</td> <td>${user.email}</td> </tr> </#list> </tbody> </table> ``` 在模板文件中,`${user.name}`、`${user.age}`和`${user.email}`是Freemarker表达式,它们将在渲染模板时被替换为实际的用户数据。 3. 准备数据 在Java代码中,您需要准备数据以便在模板中使用。您可以将数据放在一个Map对象中,其中每个键值对表示模板中的一个变量和它的值。例如,以下是一个包含三个用户的Map对象: ``` Map<String, Object> data = new HashMap<>(); List<User> users = Arrays.asList( new User("Alice", 30, "alice@example.com"), new User("Bob", 25, "bob@example.com"), new User("Charlie", 35, "charlie@example.com") ); data.put("users", users); ``` 在这里,User是一个自定义的Java类,它具有三个属性:name、age和email。 4. 渲染模板 最后,您需要将数据应用于模板并生成HTML表格。以下是一个简单的方法,使用Freemarker的Template和TemplateExceptionHandler类来完成这个任务: ``` public String generateTable(Map<String, Object> data) throws Exception { Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); cfg.setClassForTemplateLoading(getClass(), "/templates"); cfg.setDefaultEncoding("UTF-8"); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); Template template = cfg.getTemplate("table.ftl"); StringWriter out = new StringWriter(); template.process(data, out); return out.toString(); } ``` 在这里,“/templates”是存放模板文件的目录,table.ftl是您之前创建的模板文件的名称。当process方法被调用时,Freemarker使用data中的数据替换模板文件中的表达式,并将结果写入StringWriter对象中。最后,该方法将返回生成的HTML表格字符串。 希望这个简单的例子能帮助您入门Fre ### 回答2: 使用Java中的Freemarker库动态生成HTML表格,需要以下步骤: 1. 导入Freemarker库:首先需要在Java项目中导入Freemarker库。可以通过Maven或手动下载jar文件导入。 2. 创建Freemarker配置对象:创建Configuration对象,并进行必要的配置,如设置模板文件的加载路径等。 3. 创建数据模型:创建一个Java对象,用于存储要在HTML表格中展示的数据。可以包含多个属性,比如姓名、年龄等。 4. 加载模板文件:使用Configuration对象加载HTML表格的模板文件。可以是一个已经存在的HTML文件,通过Freemarker的模板语法嵌入需要动态生成的内容。 5. 创建数据模型集合:如果需要在表格中展示多条数据,可以创建一个List或数组,将多个数据模型对象添加到集合中。 6. 填充数据到模板:创建一个Template对象,并使用数据模型集合作为参数,调用process方法将数据填充到模板中。 7. 输出生成的HTML表格:将填充好数据的模板内容输出到一个HTML文件或直接返回给用户。 以下是一个简单的示例代码: ```java import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class FreemarkerExample { public static void main(String[] args) { try { // 创建Freemarker配置对象 Configuration cfg = new Configuration(Configuration.VERSION_2_3_29); cfg.setClassForTemplateLoading(FreemarkerExample.class, "/templates"); // 创建数据模型 List<Map<String, Object>> dataModels = new ArrayList<>(); Map<String, Object> dataModel1 = new HashMap<>(); dataModel1.put("name", "John"); dataModel1.put("age", 25); dataModels.add(dataModel1); Map<String, Object> dataModel2 = new HashMap<>(); dataModel2.put("name", "Alice"); dataModel2.put("age", 30); dataModels.add(dataModel2); // 加载模板文件 Template template = cfg.getTemplate("table_template.ftl"); // 填充数据到模板 Writer out = new OutputStreamWriter(System.out); template.process(dataModels, out); // 输出生成的HTML表格 out.flush(); } catch (IOException | TemplateException e) { e.printStackTrace(); } } } ``` 示例中使用了一个名为`table_template.ftl`的模板文件作为HTML表格的模板,模板中可以使用Freemarker的模板语法嵌入动态生成的内容。 以上就是使用Java中的Freemarker库动态生成HTML表格的基本流程,你可以根据实际需求进行修改和扩展。 ### 回答3: 使用Java中的Freemarker库来动态生成HTML表格可以分为以下几个步骤: 1. 引入Freemarker库:传统的方式是下载Freemarker库的jar文件然后将其添加到项目的classpath中。现代方式是使用构建工具如Maven或Gradle来管理依赖。 2. 创建Freemarker配置对象:使用Freemarker的Configuration类来创建一个配置对象。可以通过指定模板文件夹的路径来告诉Freemarker在哪里读取模板。 3. 加载模板:使用配置对象的getTemplate方法来加载模板文件。需要传入模板文件的路径和名称。 4. 创建数据模型:创建一个Java对象作为数据模型,然后将需要在表格中展示的数据放入该对象中。可以使用Map或者POJO来代表数据模型。 5. 合并数据模型和模板:创建一个Writer对象来存储生成的HTML代码。然后使用模板对象的process方法将数据模型和Writer对象作为参数传入,生成HTML代码。 6. 输出HTML代码:将Writer对象中的HTML代码输出到文件或者直接返回给HTTP响应。 总的来说,使用Freemarker生成HTML表格主要涉及创建Freemarker配置对象、加载模板、创建数据模型、合并数据模型和模板,并最终输出HTML代码。较为复杂的表格可以在模板文件中使用Freemarker的标签和指令来实现动态处理和逻辑控制,以实现更高级的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值