之前导出docx与pdf都是使用freemarker模板引擎+html文档来渲染的, 这种方式缺点在于每个模板都需要自己手动去调整改起来很不方便, 现在有了新的方式
docx文件
其实docx文件是一个压缩包, 当我们把文件的后缀名改为zip之后解压可以得到如下, 进入word目录, 有一个docment.xml文件, 我们可以编辑这个xml文件来写freemarker语法, 但是这样也是很不方便, 每次还要修改xml文件来完成模板, 所以可以引出今天要介绍的这个工具xdocreport
,
xdocreport
它的原理跟前面讲的docx文件改为zip后缀名后编辑xml一样的, 只不过这一步不需要我们手动操作了, 可以直接修改docx文档即可
注意点
制作docx模板也是有需要注意的地方, 因为我们要写freemarker语法, 所以必须保证xml中的freemarker语法是完整的所以这里需要用到代码域
wps中使用ctrl+F9来创建一个代码域, 然后右键选择编辑域
这里选择邮件合并, 在域代码中添加freemarker语法
引入maven依赖
xml
<dependencies>
<!-- XDocReport Core -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.core</artifactId>
<version>2.0.2</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- POI处理DOCX -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
<version>2.0.2</version>
</dependency>
<!-- iText转换PDF -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.itext.extension</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>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
<version>2.0.2</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.converter.odt.odfdom</artifactId>
<version>2.0.2</version>
</dependency>
工具类
java
public class XDocReportUtils {
/**
* 导出DOCX文档
*
* @param templatePath 模板文件路径
* @param outputPath 输出文件路径
* @param data 模板数据
* @throws IOException
* @throws XDocReportException
*/
public static void exportDocx(String templatePath, String outputPath, Object data)
throws IOException, XDocReportException {
// 1. 加载模板文件
InputStream in = Files.newInputStream(Paths.get(templatePath));
IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);
// 2. 创建上下文并填充数据
IContext context = report.createContext();
context.put("data", data);
// 3. 生成输出文件
OutputStream out = Files.newOutputStream(Paths.get(outputPath));
report.process(context, out);
// 4. 关闭流
in.close();
out.close();
}
/**
* 将DOCX转换为PDF
*
* @param docxPath DOCX文件路径
* @param pdfPath PDF输出路径
* @throws IOException
* @throws XDocReportException
*/
public static void convertToPdf(String docxPath, String pdfPath)
throws IOException, XDocReportException {
// 1. 加载DOCX文件
InputStream in = Files.newInputStream(Paths.get(docxPath));
IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in);
// 2. 创建空上下文
IContext context = report.createContext();
// 3. 转换为PDF
Options options = Options.getTo(ConverterTypeTo.PDF);
OutputStream out = Files.newOutputStream(Paths.get(pdfPath));
report.convert(context, options, out);
// 4. 关闭流
in.close();
out.close();
}
/**
* 从模板直接导出PDF
*
* @param templatePath 模板文件路径
* @param pdfPath PDF输出路径
* @param data 模板数据
* @throws IOException
* @throws XDocReportException
*/
public static void exportPdf(String templatePath, String pdfPath, Object data)
throws IOException, XDocReportException {
// 1. 加载模板
InputStream in = Files.newInputStream(Paths.get(templatePath));
IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);
// 2. 创建上下文并填充数据
IContext context = report.createContext();
context.put("data", data);
// 3. 直接导出为PDF
OutputStream out = Files.newOutputStream(Paths.get(pdfPath));
Options options = Options.getTo(ConverterTypeTo.PDF);
report.convert(context, options, out);
// 4. 关闭流
in.close();
out.close();
}
public static void main(String[] args) throws IOException, XDocReportException {
Map<String, String> map = new HashMap<>();
map.put("name", "John Doe");
map.put("age", "30");
// exportDocx("D:\\template.docx", "D:\\output.docx", map);
exportPdf("D:\\template.docx", "D:\\output.pdf", map);
}
}
测试
注意点
测试过程中很容易出现这种问题, 中文字符无法显示出来, 这一般是跟字体有关系, 确保docx模板中的字体在本地是有相应的字符集的, 例如我改为了宋体, 这里就没有问题了, 同理, 当要上测试或生产环境时, 一定要保证服务器中是有相应的字符集的