xdocreport+freemarker导出docx&pdf

之前导出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模板中的字体在本地是有相应的字符集的, 例如我改为了宋体, 这里就没有问题了, 同理, 当要上测试或生产环境时, 一定要保证服务器中是有相应的字符集的

相关推荐
AI人工智能+电脑小能手44 分钟前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
来杯@Java2 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记2 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥2 小时前
匿名函数 lambda + 高阶函数
java·python·算法
東雪木3 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
adrninistrat0r3 小时前
Java调用链MCP分析工具
java·python·ai编程
噜噜噜阿鲁~3 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
春生野草4 小时前
反射、Tomcat执行
java·开发语言
_日拱一卒4 小时前
LeetCode:207课程表
java·数据结构·算法·leetcode·职场和发展
飞翔中文网4 小时前
Java学习笔记之抽象类与接口(设计思想)
java·笔记·学习