XDocReport介绍
初步了解XDocReport
适用范围
XDocReport是一个用来进行文档填充和文档格式转换的java api。在一些项目中,我们可能需要对一份模板里的某些字段进行填充,比如电子合同中需要填写双方信息以及一些金额数据。这时候,我们就可以用XDocReport来实现我们的功能。如果需要把word文档转成pdf,也可以用XDocReport,但是其对中文支持不太好,可能需要用其它工具。所以这篇文章也主要介绍如何使用XDocReport进行文档填充。
文档填充支持的格式包括docx和odt,docx可以使用Office创建和查看,odt可以使用openoffice和libreoffice创建和查看。两种文档在设计模板上会有些许不同,在代码上没有任何区别,下面会详细介绍。
源码地址
在git上可以找到XDocReport的源码。在其README.md里有详细的Getting Started。通过官方教程,可以非常快速且详细地了解其使用方法。
模板引擎
XDocReport使用的模板引擎是freemarker和velocity,如果想具体什么是模板引擎以及上述两者模板引擎有什么区别,可以找些文章看看。需要提醒的是,官方教程大多数采用的是velocity(当然也有介绍freemarker),但是我这采用的freemarker。二者的填充占位符有所不同,这点需要注意,如果设置反了自然就不会填充成功了。
一个填充的简单例子
需求设计
这里我们先模拟下需求:完成一份项目文档,需要填充的内容包括项目文档的标题、项目信息、相关人员信息以及一个logo。这里涉及的填充包括字符串填充,pojo填充,list填充以及图片填充,基本可以满足99%的实际需求。接下去,我们需要设计模板,然后再根据模板设计代码,最后进行测试。
设计填充模板
最终效果图
我先展示模板的最终图(freemarker的占位符):
填充字段设置
首先是字段占位符的设置。我们的文档是docx格式,用office打开后,在你需要填充的地方,先按ctrl+f9,是不是出现了一对有阴影的括弧?如果没出现,可能是因为开启了笔记本上F1-F12的快捷键。在括弧上右键,选择“编辑域”,然后选择“MergeField”(如果是中文的就找找看意思相近的,貌似是邮件合并)。接着在上面填写占位符,如果到时候在程序上选择freemarker模板引擎,那么占位符就是 . . . , 占 位 符 里 填 写 占 位 的 字 符 串 。 如 果 是 v e l o c i t y 模 板 引 擎 , 那 么 占 位 符 就 是 {...},占位符里填写占位的字符串。如果是velocity模板引擎,那么占位符就是 ...,占位符里填写占位的字符串。如果是velocity模板引擎,那么占位符就是,然后后面填写占位的字符串。由于我打算用freemarker,所以可以从图片里看到,我的都是${…}。总结一下就是,ctrl+f9 -> 邮件编辑域 -> MergeField -> 填写占位符。
如果填充的文档是odt格式,那么只需要填写占位符就好了。
我对填充字段的理解
上面也说过,填充的数据会包括字符串、pojo、list,所以他们占位符里的字段其实是不太一样的。其实,可以理解成java传到模板里的数据就是一个对象,如果对象是string,那么填充的就是其本身,如title;如果对象里包括多个成员变量,那么填充的就是对象里的成员变量,如project. name 和 project. info;如果对象是个list,那么其实在模板里是一样的,但是在java程序里会有所不同。
图片填充设置
说完了字段的填充,最后再说下图片的填充。图片的话,先随便插入一张图片,然后点下图片,对图片插入书签,设置书签名。OK,这样模板就搞定了。
代码编写
maven依赖
<dependencies>
<!--xdocreport必备的依赖-->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.document</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.core</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.template</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.converter</artifactId>
<version>2.0.1</version>
</dependency>
<!--模板引擎相关-->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
<version>2.0.1</version>
</dependency>
<!--文档格式相关-->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
如果采用velocity引擎,或者文档格式为odt,那么就需要换成相应的依赖。
填充类
Project类
public class Project {
private String name;
private String info;
省略set、get和全参构造器
}
Employee类
public class Employee {
private String name;
private String job;
private String result;
//省略set、get和全参构造器
}
模板加载
//1.通过freemarker模板引擎加载文档,并缓存到registry中
InputStream in = new FileInputStream(
"E:\\project\\xdocreport\\file\\test.docx");
IXDocReport report = XDocReportRegistry
.getRegistry()
.loadReport(in, TemplateEngineKind.Freemarker);
这里指定了模板路径以及模板引擎。
设置域
//2.设置填充字段、填充类以及是否为list。
FieldsMetadata fieldsMetadata = report.createFieldsMetadata();
fieldsMetadata.load("project", Project.class);
fieldsMetadata.load("employees", Employee.class, true);
fieldsMetadata.addFieldAsImage("logo");
report.setFieldsMetadata(fieldsMetadata);
结合之前写的模板里的填充字段,也就是域,可以发现
- title只是一个字符串,并不需要设置;
- project和employees的区别在于project是单个对象,而employees是多个对象的集合。所以这里employees要加个"true",表明它是个List。
- 图片设置和字段设置有所区别
- 这里设置的域的名字要和模板里的名字保持一致
模拟填充数据
//3.模拟填充数据
String title = "项目开发报告";
Project project = new Project("网站开发", "截至2018年年底");
List<Employee> employees = new ArrayList<Employee>();
employees.add(new Employee("张三", "产品", "任务完成"));
employees.add(new Employee("李四", "开发", "任务完成"));
IImageProvider logo = new FileImageProvider(
new File("E:\\project\\xdocreport\\file\\1.jpg"),
true);
logo.setSize(200f, 100f);
开始填充
//4.匹配填充字段和填充数据,进行填充
IContext context = report.createContext();
context.put("title", title);
context.put("project", project);
context.put("employees", employees);
context.put("logo", logo);
OutputStream out = new FileOutputStream(
new File("E:\\project\\xdocreport\\file\\test-out.docx"));
report.process(context, out);
测试结果
更多内容…
Getting Started的内容非常详细,还有能多内容没来得及看。
第一次更新:2018.12.2