首页 > 其他分享 >根据模板动态生成word(一)使用freemarker生成word

根据模板动态生成word(一)使用freemarker生成word

时间:2023-07-09 21:22:37浏览次数:39  
标签:word String freemarker 生成 put new dataMap 模板

@

目录

一、准备模板

1、创建模板文件

首先先建立一个word文件,输入模板内容freemaker的内容,下面是本次演示的word文件。
docx格式演示word模板

然后将word文件另存为 .xml 文件,然后再把文件后缀改成.ftl 。将项目的resource目录下建立一个templates目录(非必须步骤)将 模板文件放到templates目录下
请添加图片描述

请添加图片描述
打开模板文件按 Ctrl + Shift + L 将模板内容格式化。

2、处理模板

2.1 处理普通文本

处理文本比较简单,将需要替换文本中直接用占位符 ${} 替换即可。

这里发现一个问题因为之前在word格式时我就已经替换了变量,但是在ftl变量却被 拆分成多段了(见图1)。但是这样是freemaker是无法成功替换变量的,所以需要手动处理成到一个段里(如图2),关于这点实在太无语了,因为没有找到比较好的处理办法,只能手工处理,在实际的开发工作中曾经花了几个小时来做这件事情。
图1:
请添加图片描述

图2
请添加图片描述

2.2 处理表格

如果模板里需要用变量填充表格,建议模板里的表格像word文件一样建一个两行的表格。在模板中<<w:tbl>> 表示一个表格 、<w: tr> 表示一行、<w: tc> 表示一列。因为FreeMarker 是利用列表一行一行循环填充的,所以我们可以根据关键字找到<<w:tbl>>标签,因为第一个 <w: tr>是表头注意不要改到了,找到第二个<w: tr>在前后分别加上如下语句即可,后面的表格里后面的行<w: tr>需要删掉,建议模板里的表格像word文件一样建一个两行的表格即可这样就不用删了:

<#list itemList as item>
</#list>

替换后的模板如下:
请添加图片描述

2.3 处理图片

如果模板里需要用变量填充图片,建议先在word文件里插入一张图片,这样在模板文件里找到<pkg:binaryData>标签直接里面把里面的图片base64字符替换成变量即可,word里可以通过植入base64字符来展示图片:

替换前:
请添加图片描述

替换后:

<pkg:binaryData>${image1}</pkg:binaryData>

到此模板已经调整完成,接下来就可以开始写代码了。

二、项目代码

1、引入依赖

在项目的pom文件里引入如下依赖

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

2、生成代码

将图片转成Base64字符串的公共方法:

public static String getImageBase64Str(String imgFile) {
        try( InputStream in = new FileInputStream(imgFile)) {
            byte[] data = new byte[in.available()];
            in.read(data);
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(data);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

根据模板文件生成word,主要生成的word的文件后缀必须是doc不能是docx,不然生成的文件无法打开。

public static void crateWord(Map<String, Object> dataMap, String templatePath, String targetFile){
        String path = templatePath.substring(0,templatePath.lastIndexOf("/"));
        String templateName = templatePath.substring(templatePath.lastIndexOf("/") + 1);
        try (FileOutputStream out = new FileOutputStream(targetFile);
             Writer writer = new BufferedWriter(new OutputStreamWriter(out, "utf-8"))){
            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            configuration.setDefaultEncoding("utf-8");
            configuration.setClassForTemplateLoading(FreeMakerTest.class, path);
            //除了ClassForTemplateLoading外,另一种模板加载方式DirectoryForTemplateLoading,也可用
            //ClassPathResource resource = new ClassPathResource(path);
            //configuration.setDirectoryForTemplateLoading(resource.getFile());
            //加载模板
            Template template = configuration.getTemplate(templateName);
            //渲染模板
            template.process(dataMap, writer);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (TemplateException e) {
            throw new RuntimeException(e);
        }
    }

三、验证生成word

新建的列表数据实体类:

public class Arrears{
    private String name;
    private Integer num;

    private String endDay;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    public String getEndDay() {
        return endDay;
    }

    public void setEndDay(String endDay) {
        this.endDay = endDay;
    }
}

准备模板填充数据

private static Map<String, Object> prepareParam(){
        LocalDate currentDate = LocalDate.now();
        LocalDate endDate = currentDate.plusYears(1L);
        List<Arrears> arrearsList = new ArrayList<>();
        arrearsList.add(new Arrears(){{setName("一顿老魏");setNum(1);setEndDay("三月内");}});
        arrearsList.add(new Arrears(){{setName("贵州大黄牛");setNum(1);setEndDay("一年内");}});
        arrearsList.add(new Arrears(){{setName("v我50");setNum(1);setEndDay("一月内");}});

        //填充所需要的数据
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("debtor", "陈有楚");
        dataMap.put("nowYear", String.valueOf(currentDate.getYear()));
        dataMap.put("nowMonth", String.valueOf(currentDate.getMonthValue()));
        dataMap.put("nowDay", String.valueOf(currentDate.getDayOfMonth()));
        dataMap.put("arrears", "一顿老魏、贵州大黄牛、v我50");
        dataMap.put("endYear", String.valueOf(endDate.getYear()));
        dataMap.put("endMonth", String.valueOf(endDate.getMonthValue()));
        dataMap.put("endDay", String.valueOf(endDate.getDayOfMonth()));
        dataMap.put("arrearsList", arrearsList);
        dataMap.put("image1", getImageBase64Str("D:\\picture\\其他\\24-05-23-142418.png"));
        dataMap.put("creditor", "知北游");
        return dataMap;
    }

测试代码:

public static void main(String[] args) throws IOException {
        //准备参数
        Map<String, Object> dataMap = prepareParam();
        crateWord(dataMap,"/templates/qiantiao.ftl","D:\\test\\qiantiao.doc");
    }

测试结果:
请添加图片描述

标签:word,String,freemarker,生成,put,new,dataMap,模板
From: https://www.cnblogs.com/fhey/p/17539412.html

相关文章

  • 在一定区间内生成n个随机数
    packagePTACZW;//随机函数//输入一个n;//随机出项1~n的数importjava.util.Scanner;importjava.util.Random;importjava.util.Set;importjava.util.HashSet;importjava.util.ArrayList;publicclassMain{publicstaticvoidmain(String[]args){......
  • 算法题-生成窗口最大值数组
    https://leetcode.cn/problems/sliding-window-maximum/ classSolution{publicint[]maxSlidingWindow(int[]nums,intk){if(nums==null||nums.length==0||k<0){returnnull;}int[]result=newint[nums.length-k+1];......
  • AI绘画:StableDiffusion炼丹Lora攻略-实战萌宠图片生成
    写在前面的话近期在小红书发现了许多极其可爱、美观的萌宠图片,对这些美妙的图像深深着迷于是想着看看利用AI绘画StableDiffusion以下简称(SD)做出来。以下是详细实操的全过程,包括所有用的资料已经打包到网盘。最后尝试的最终效果如下:更多图片请查看网盘:「萌宠图片及关键词」......
  • 20230709 - 一句SQL更新WordPress管理员密码
    该方法适用于有wordpress数据库权限,但忘记了管理员密码的情况UPDATEwp_usersSETuser_pass=MD5('new_password')WHEREwp_users.user_login='admin_username';更新时,密码为MD5加密字符串,此时可以使用new_password登录,登录后,WordPress会自动更新密码为新加密字符格式。......
  • 列表生成器
    #自动生成123l=list(range(1,4))print(l)#求1*12*23*3l2=[]forxinrange(1,4):l2.append(x*x)print(l2)#简化print([x*xforxinrange(1,4)])#求x*x中的偶数print([x*xforxinrange(1,4)ifx%2==0])#求双层循环print([m+nfor......
  • delphi 生成重复字符串
    生成重复字符串代码重复字符或字符串usesSystem.StrUtils;procedureTForm1.Button1Click(Sender:TObject);vars:string;begin//返回重复字符s:=StringOfChar('A',10);Memo1.Lines.Add(s);//返回重复字符串s:=DupeString('ABC',5);Memo1.Lin......
  • Meta 正式开源音乐生成模型 MusicGen
    导读Meta近日在Github上开源了其音乐生成模型MusicGen。据介绍,MusicGen主要用于音乐生成,它可以将文本和已有的旋律转化为完整乐曲。该模型基于谷歌2017年推出的Transformer模型。研发团队表示:“我们使用了20000小时的授权音乐来对训练该模型,并采用Meta的EnC......
  • Wordpress:如何更改Elementor绑定的网站?
    在使用Wordpress做网站的过程中,需要用到Elementor付费版进行优化网站,一般是绑定一个网站后,要想新建另一个网站,基础版不支持多个绑定,那么如何进行改绑呢?1.进入Elementor后台,选择Subscriptions >>>选择已绑定的项,点击右下角ManageThissubscription  2.点击网站后面的锁......
  • 如何在excel中链接到word的指定位置
    Excel中创建超链接跳转到Word文档-百度经验(baidu.com)本人使用的是方法一excel中是如下输入: ......
  • 【git】代码patch包生成和合入
    patch合入gitamgitam会直接将patch的所有信息打上去,而且不用重新gitadd和gitcommit,author也是patch的author而不是打patch的人常用命令gitam0001-limit-log-function.patch#将名字为0001-limit-log-function.patch的patch打上gitam--signoff0001-limit-......