XDocReport
简介
XDocReport是GitHub上根据麻省理工学院许可证开源的Wrod导出框架。XDocReport可以根据ODT、Doc、Docx文档模板通过模板引擎语法(Freemarker、Velocity)转换为另外一种格式文档(Doc、Docx、XHTML、PDF)。
XDocReport特性
XDocReport是模块化而且非常轻便(不需要在你的服务器安装MS Office、LiberOffice)。你可以选择要管理的XML类型文档(docx、odt…)和选择熟悉的模板引擎(Freemarker、Velocity)组合使用。
- 支持OpenOffice、MS Word格式。
- 默认支持Freemarker、Velocity语法,也可以自己扩展语法。
- 支持报告生成的调试过程。
- 支持表格循环遍历。
- 支持动态图像替换。
- 在OSGI环境中管理XDcoReport。
- 支持格式转换器,默认支持的转换器(ODT 2 PDF、Docx 2 PDF).
- 支持实现自己的模板引擎。默认情况下实现了FreeMarker、Velocity。
- 支持转换器扩展。默认实现了ODT 2 PDF(通过ODFDOM+iText)、Docx 2 PDF(通过POI+iText)。
基本原理
工具类封装
package org.leaf.word.xdocreport;
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 java.io.FileInputStream;
import java.io.IOException;
public class WordUtils {
public static ExportData getExportData(String url) throws IOException, XDocReportException {
final IXDocReport report = createReport(url);
final IContext context = report.createContext();
return new ExportData(report, context);
}
private static IXDocReport createReport(String url) throws IOException, XDocReportException {
final FileInputStream fileInputStream = new FileInputStream(url);
return XDocReportRegistry.getRegistry().loadReport(fileInputStream, TemplateEngineKind.Freemarker);
}
}
package org.leaf.word.xdocreport;
import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
import java.io.IOException;
import java.io.OutputStream;
public class ExportData {
private IXDocReport report;
private IContext context;
public ExportData(IXDocReport report, IContext context) {
this.report = report;
this.context = context;
}
public void process(OutputStream out) throws IOException, XDocReportException {
report.process(context, out);
}
public void setData(String key, Object value) {
FieldsMetadata fieldsMetadata = report.getFieldsMetadata();
fieldsMetadata = fieldsMetadata == null ? new FieldsMetadata() : fieldsMetadata;
fieldsMetadata.addFieldAsList(key);
context.put(key, value);
}
}
快速开始
模板
- 创建ODTHelloWordWithVelocity.docx文档,输入内容Hello ${name}。
- ${name}设置步骤
- Ctrl + F9,选择邮件合并类型,输入"${name}"
Maven
<!--org.leaf.word.to.pdf.aspose-->
<dependencies>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/xdocreport -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>xdocreport</artifactId>
<version>${xdocreport.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.document.docx -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
<version>${xdocreport.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.template -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
<version>${xdocreport.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.template -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.document</artifactId>
<version>${xdocreport.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.template -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.core</artifactId>
<version>${xdocreport.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.template -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.converter</artifactId>
<version>${xdocreport.version}</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
<version>${xdocreport.version}</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.template.velocity</artifactId>
<version>${xdocreport.version}</version>
</dependency>
</dependencies>
示例代码
public static void main(String[] args) throws IOException, XDocReportException {
final ExportData exportData = WordUtils.getExportData("F:\\idea-workspace\\my_source\\word-document\\src\\main\\resources\\xdocreport\\ODTHelloWordWithVelocity.docx");
exportData.setData("name", "world");
exportData.process(new FileOutputStream("F:\\idea-workspace\\my_source\\word-document\\src\\main\\resources\\xdocreport\\ODTHelloWordWithVelocity_out.docx"));
}
结果
基本设置
普通域对象
图片对象
图片对象的设置使用书签设置
数据设置
Java
package org.leaf.word.xdocreport;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import fr.opensagres.xdocreport.core.XDocReportException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo1 {
public static void main(String[] args) throws IOException, XDocReportException {
final ExportData exportData = WordUtils.getExportData("F:\\idea-workspace\\my_source\\word-document\\src\\main\\resources\\xdocreport\\ODTHelloWordWithVelocity.docx");
exportData.setData("data", readJSON());
exportData.process(new FileOutputStream("F:\\idea-workspace\\my_source\\word-document\\src\\main\\resources\\xdocreport\\ODTHelloWordWithVelocity_out.docx"));
}
public static JSONObject readJSON() throws IOException {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(new File("F:\\idea-workspace\\my_source\\word-document\\src\\main\\resources\\xdocreport\\xdocreport.json"), JSONObject.class);
}
}
JSON
{
"userName": "张三",
"applyDate": "2022-12-12",
"applyDetail": [
{
"sqxm": "北京出差",
"sqje": 123458.695,
"sxmx": "住宿",
"sqr": "张三",
"sqrq": "2022-12-26"
},
{
"sqxm": "北京出差",
"sqje": 1238.695,
"sxmx": "路费",
"sqr": "张三",
"sqrq": "2022-12-26"
},
{
"sqxm": "北京出差",
"sqje": 128.695,
"sxmx": "吃饭",
"sqr": "张三",
"sqrq": "2022-12-26"
}
],
"list": ["1、飞机票", "2、电影票", "3、住宿发票"]
}
文本
普通文本使用${}
条件
条件使用[#if condition] [/#if]
表格
表格使用@before-row[#list data as d]和@after-row[/#list]表示遍历的开始和结束,文本的输入和普通文本一样
列表
列表遍历使用[#list data.list as l]开始和[/#list]结束