Java使用FreeMarker自动生成word文档(可遍历生成多张图片)

本文档介绍了如何使用Java结合FreeMarker模板引擎来动态生成包含多张图片的Word文档。通过设置模板,将图片转为base64编码并替换占位符,实现了遍历循环生成标题和图片的功能。文章详细讲解了每个步骤,包括模板的创建、XML到FTL的转换,以及代码实现过程。

Java使用FreeMarker自动生成word文档(可遍历生成多张图片)

  1. 前言:最近项目中后台需要自动生成word文档,我以前也没做过,就百度了下,发现还是用freemarker生成word文档最快,但是试了网上的一些方法,都没成功,最后参考着多篇文章慢慢摸索最终成功了。在这记录一下。
  2. 需要实现的效果图
    在这里插入图片描述
  3. 首先,导入Jar包依赖
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.28</version>
		</dependency>
  1. 制定模板

在这里插入图片描述
注意:这一步图片都先别用占位符,因为用占位符就不知道这是图片了(我这种方式我认为是这样的,因为我试过用图片先用占位符,发现一直生成不了图片)

  1. 将模板另存为xml
    在这里插入图片描述
    生成xml时,图片全部被转成base64了,这时候需要删除掉,用占位符${user.photo}
    在这里插入图片描述
    在这里插入图片描述
  2. 然后直接重命名,将文件格式改为ftl
  3. 接下来需要修改ftl,因为我需要遍历循环生成标题和图片(重点)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    8.至此,模板已经制作完成,下面写代码
package com.chinobot.util.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;

/**
 * Word文档工具类
 */
public class WordUtil {

    /**
     * 使用FreeMarker自动生成Word文档
     * @param dataMap   生成Word文档所需要的数据
     * @param fileName  生成Word文档的全路径名称
     */
    public static void generateWord(Map<String, Object> dataMap, String fileName) throws Exception {
        // 设置FreeMarker的版本和编码格式
        Configuration configuration = new Configuration(new Version("2.3.28"));
        configuration.setDefaultEncoding("UTF-8");

        // 设置FreeMarker生成Word文档所需要的模板的路径
        configuration.setClassForTemplateLoading(WordUtil.class, "/templates/code");
        // 设置FreeMarker生成Word文档所需要的模板
        Template t = configuration.getTemplate("zs.ftl", "UTF-8");
        // 创建一个Word文档的输出流
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(fileName)), "UTF-8"));
        //FreeMarker使用Word模板和数据生成Word文档
        t.process(dataMap, out);
        out.flush();
        out.close();
    }

}

package com.chinobot.util.util;

import org.springframework.util.StringUtils;

import org.apache.commons.codec.binary.Base64;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 图片工具类
 */
public class ImageUtil {

    /**
     * 将图片内容转换成Base64编码的字符串
     * @param imageFile 图片文件的全路径名称
     * @return 转换成Base64编码的图片内容字符串
     */
    public static String getImageBase64String(String imageFile) {
        if (StringUtils.isEmpty(imageFile)) {
            return "";
        }
        File file = new File(imageFile);
        if (!file.exists()) {
            return "";
        }
        InputStream is = null;
        byte[] data = null;
        try {
            is = new FileInputStream(file);
            data = new byte[is.available()];
            is.read(data);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return Base64.encodeBase64String(data);
    }

}
package com.chinobot.util.util;
import com.chinobot.util.util.WordUtil;
import com.chinobot.wordxml.entity.FileXml;
import com.chinobot.wordxml.entity.RecordXml;
import com.chinobot.wordxml.entity.UserXml;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Java使用FreeMarker生成Word文档主程序
 */

public class WordApplication {

    public static void main(String[] args) throws Exception {

        /**
         * 自动生成Word文档
         * 注意:生成的文档的后缀名需要为doc,而不能为docx,否则生成的Word文档会出错
         */
        WordUtil.generateWord(getDate(), "d:\\home\\tem\\user3.doc");
    }


    private static Map<String, Object> getDate(){

        Map<String, Object> dataMap = new HashMap<>();
        UserXml user = new UserXml();
        user.setRealName("李红");
        user.setPhoto(ImageUtil.getImageBase64String("d:\\home\\tem\\1.jpg"));
        user.setDateOfBirth("2020-05-11");
        user.setAge("44");
        user.setNation("汉族");
        user.setGender("女");
        user.setIdNumber("362532199812171215");
        user.setInboundTime("2020-25-12");
        user.setInboundWay("康宁医院");
        user.setInBeds("5号床位");
        user.setPhysicalConditions("健康");
        user.setMentalState("正常");
        user.setAddress("广东省深圳市宝安区西乡街道");
        user.setCensusMessage("广东省深圳市");
        user.setMessageCollect("指纹");
        user.setPushChannel("让爱回家 | i深圳");
        dataMap.put("user",user);

        RecordXml record = new RecordXml();
        record.setTitle("线索记录");
        List<String> messagelist = new ArrayList();
        messagelist.add("第一行");
        messagelist.add("第二行");
        record.setMessageList(messagelist);

        RecordXml record2 = new RecordXml();
        record2.setTitle("回复记录");
        List<String> messagelist2 = new ArrayList();
        messagelist2.add("第三行");
        messagelist2.add("第四行");
        record2.setMessageList(messagelist2);

        List<RecordXml> recordList = new ArrayList<>();
        recordList.add(record);
        recordList.add(record2);
        dataMap.put("messList",recordList);

        FileXml file = new FileXml();
        file.setTitle("图1  测试标题");
        file.setPic(ImageUtil.getImageBase64String("d:\\home\\tem\\4.png"));

        FileXml file2 = new FileXml();
        file2.setTitle("图2  测试标题2");
        file2.setPic(ImageUtil.getImageBase64String("d:\\home\\tem\\3.jpg"));
        List<FileXml> fileList = new ArrayList<>();
        fileList.add(file);
        fileList.add(file2);
        dataMap.put("fileList",fileList);

        return dataMap;
    }
}
  1. 至此,就已经结束了,当然以上实体类中的属性必须全部不能为空,否者就会报错。
    解决方案:给为空的一个默认值 ${(user.inStationNumber)!’’}
    集合也需要做判断在这里插入图片描述
    结束!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值