Java根据自定义模板生成Word

写在前面:此文章为本人学习过程,路过大神不喜勿喷

一、思路

基础使用的是XDocReport这个组件,GitHub地址附上:XDocReport
全英文使用说明,英语好或感兴趣的小伙伴可以直接看原文介绍
再说下我的思路,简单来说就是根据标识替换文字
先在Word中编辑好自己想生成的模板,替换内容即可

二、实现

1、添加必须要使用到的类库Maven地址

<dependency>
	<groupId>fr.opensagres.xdocreport</groupId>
	<artifactId>fr.opensagres.xdocreport.core</artifactId>
	<version>2.0.2</version>
</dependency>
<dependency>
	<groupId>fr.opensagres.xdocreport</groupId>
	<artifactId>fr.opensagres.xdocreport.document</artifactId>
	<version>2.0.2</version>
</dependency>
<dependency>
	<groupId>fr.opensagres.xdocreport</groupId>
	<artifactId>fr.opensagres.xdocreport.template</artifactId>
	<version>2.0.2</version>
</dependency>
<dependency>
	<groupId>fr.opensagres.xdocreport</groupId>
	<artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
	<version>2.0.2</version>
</dependency>
<dependency>
	<groupId>fr.opensagres.xdocreport</groupId>
	<artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
	<version>2.0.2</version>
</dependency>

2、为了方便构建和操作,我先封装好自己所需要的工具类

import lombok.Data;

// 此类为方便对应模板中的对应值使用
@Data
public class Column {
    private String a;
    private String b;
    private String c;
    private String d;
    private String e;
    private String f;
    private String g;
    private String h;
    private String i;
    private String j;
    private String k;
    private String l;
    private String m;
    private String n;
    private String o;
    private String p;
    private String q;
    private String r;
    private String s;
    private String t;
    private String u;
    private String v;
    private String w;
    private String x;
    private String y;
    private String z;


    public Column() {
    }
    // 此处建议手动生成从1个参数的构造器到全参数构造器,方便之后创建对象
    // 也可根据自己生成模板中的情况生成对应个数的构造方法
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;

import java.util.HashMap;
import java.util.Map;

// 转化字段为填充表格的字段
public class FieldMappingUtil {
    private static Map<String, Map<String, String>> MAPPING = new HashMap<>();
    
    // 此处线优先声明好字段的映射关系
    static {
        Map<String, String> userMapping = new HashMap<>();
        userMapping.put("name","a");
        userMapping.put("age","b");
        MAPPING.put("user", userMapping);
    }

    /***
     * @method change
     * @Description //TODO  转化
     * @param o o 需要转化的对象
     * @param mapping mapping 字段映射关系
     * @return com.hbisdt.ghg2.entity.Column
     **/
    public static Column change(Object o, String mapping) {
        CopyOptions copyOptions = CopyOptions.create();
        copyOptions.setFieldMapping(MAPPING.get(mapping));
        return BeanUtil.toBean(o, Column.class, copyOptions);
    }
}
import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;

import java.io.*;
import java.util.List;

public class MyXDocReport {

    private final IXDocReport report;
    private final IContext context;
    private final FieldsMetadata fm;

    public MyXDocReport(String path) throws Exception {
//        InputStream ins = this.getClass().getResourceAsStream(path);
        InputStream ins = new FileInputStream(new File(path));
        //注册xdocreport实例并加载FreeMarker模板引擎
        this.report = XDocReportRegistry.getRegistry().loadReport(ins, TemplateEngineKind.Freemarker);
        //创建xdocreport上下文对象
        this.context = this.report.createContext();
        //创建字段元数据
        this.fm = this.report.createFieldsMetadata();
    }

    /**
     * 存入对应值
     * @param key
     * @param obj
     * @throws XDocReportException
     */
    public void put(String key, Object obj) throws XDocReportException {
        if (obj instanceof String) {
            this.context.put(key, obj);
        } else if (obj instanceof List) {
            this.context.put(key, obj);
            this.fm.load(key, Column.class, true);
        } else if (obj instanceof Column) {
            this.context.put(key, obj);
            this.fm.load(key, Column.class, false);
        }
    }

    /**
     * 获取对应值
     * @param key
     * @return
     */
    public Object get(String key){
       return this.context.get(key);
    }


    /**
     * 对外输出流
     * @param out
     * @throws Exception
     */
    public void process(OutputStream out) throws Exception {
        this.report.process(context, out);
    }

}

下面类中使用到了Hutool工具包中的方法,请按需添加

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;

import java.util.HashMap;
import java.util.Map;

// 转化字段为填充表格的字段
public class FieldMappingUtil {
    private static Map<String, Map<String, String>> MAPPING = new HashMap<>();
    
    // 此处优先声明好字段的映射关系
    static {
        Map<String, String> userMapping = new HashMap<>();
        userMapping.put("name","a");
        userMapping.put("age","b");
        MAPPING.put("user", userMapping);
    }

    /***
     * @method change
     * @Description //TODO  转化
     * @param o o 需要转化的对象
     * @param mapping mapping 字段映射关系
     * @return com.hbisdt.ghg2.entity.Column
     **/
    public static Column change(Object o, String mapping) {
        CopyOptions copyOptions = CopyOptions.create();
        copyOptions.setFieldMapping(MAPPING.get(mapping));
        return BeanUtil.toBean(o, Column.class, copyOptions);
    }
}

3、构建操作程序

public class Test {
    public static void main(String[] args) throws Exception {
        MyXDocReport myXDocReport = new MyXDocReport("D:/userTemplate.docx");
        // 1、 对象填充
        // 假设我们从数据库查询出一条用户信息
        User user = new User("张三", 28);
        Column userColumn = FieldMappingUtil.change(user, "user");
        myXDocReport.put("user", userColumn);

        // 2、纯文字填充
        myXDocReport.put("str", "我是张三, 今年28岁!");

        // 3、多段文字填充
        List<String> list = new ArrayList<>();
        list.add("山哪里有天才,我是把别人喝咖啡的虹夫都用在学习上的。-鲁迅");
        list.add("世上无难事,只要肯攀登。-毛泽东");
        list.add("天才出于勤奋。-高尔基");
        list.add("人类要在竞争中生存,便要奋斗。-孙中山");
        list.add("天才在于积累,聪明在于勤奋。-华罗庚");
        list.add("业精于,荒于嬉;行成于思,毁于随。-韩愈");
        myXDocReport.put("listS", list);

        // 4、 插入图片
        IImageProvider logo = new FileImageProvider(
                new File("D:/car.jpg"),
                true);
        myXDocReport.put("logo", logo);

        // 5、插入列表
        List<Column> listA = new ArrayList<>();
        listA.add(FieldMappingUtil.change(new User("张三",29),"user"));
        listA.add(FieldMappingUtil.change(new User("李四",21),"user"));
        listA.add(FieldMappingUtil.change(new User("王五",19),"user"));
        listA.add(FieldMappingUtil.change(new User("陈六",30),"user"));
        myXDocReport.put("listA", listA);




        File file = new File("D:/output.docx");
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream out = new FileOutputStream(file);
        myXDocReport.process(out);
    }

    @Data
    static class User {
        String name;
        Integer age;

        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }
}

4、构建模板(此处需要知道一个名词:域)

Java根据自定义模板生成Word_第1张图片

根据上面动图操作可以设计模板

Java根据自定义模板生成Word_第2张图片

图片插入(需要预先插入一张模板图片,点击选中图片->选择顶部工具栏插入->书签->写入书签名->添加)
插入图片时的模板图片:
模板图片
运行程序,生成结果

Java根据自定义模板生成Word_第3张图片

OK~
最后的最后:希望文章可以帮到大家,路过大神不喜勿喷,我们共同学习,加油吧!!!!

你可能感兴趣的:(Java,java)