XDocReport文书生成总结

最近弄一个业务需要搞很多的word文档导出,供前端下载。之前的实现方式一般是先把word转成XML格式,然后赋值变量,这种方式虽然可行,但是遇到那种长篇且变量又多的文档,就很让人头大,密密麻麻的一堆代码,看着十分繁乱,不好修改模板。于是在技术选型上找到了XDocReport,该技术可以直接使用word文档作为模板,使用Velocity或Freemarker语法来设置要替换的变量,从而实现复杂的文档导出。

一.XDocReport技术Java实现

使用该模板的操作主要是 IXDocReport 和 IContext 对象,封装两个工具类来对他们进行获取和操作,用 IContext 的 put(key,value)赋值模板变量即可

java 复制代码
 //获取Word模板,模板存放路径在项目的resources目录下template文件夹
 InputStream ins = this.getClass().getClassLoader().getResourceAsStream("template" +
             File.separator + "test.docx");
 IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins,
             TemplateEngineKind.Freemarker);
//创建xdocreport上下文对象
IContext context = report.createContext();
//创建字段元数据
FieldsMetadata fm = report.createFieldsMetadata();

//1.业务逻辑
//2.模板传递参数
//2.1集合变量
context.put("certList", certificateList);
fm.load("certList", CbgkShipCertificate.class, true);
//2.2实体变量
context.put("cancelCertify", cancelCertifyVO);
fm.load("cancelCertify", CbgkCancelCertifyVO.class, false);
//2.3单一变量
context.put("moreCatalog", 0);
//2.4图片变量
fm.addFieldAsImage("imgUrl");
File file = UrltoFile(personImage.getUrl());     //该方法在下头
IImageProvider iImageProvider = new FileImageProvider(file, false);
context.put("imgUrl", iImageProvider);
report.setFieldsMetadata(fm);

response.setContentType("application/msword");
response.setCharacterEncoding("UTF-8");
String fileName = URLEncoder.encode(peopleInfoVO.getName() + "综合材料.docx", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
try (ServletOutputStream outputStream = response.getOutputStream()) {
      report.process(context, outputStream);
      outputStream.flush();
}
java 复制代码
    /**
     * 将Url转换为File
     * @param url
     * @return
     * @throws Exception
     */
    public static File UrltoFile(String url) throws Exception {
        log.error("图片的url: " + url);
        InputStream ins = null;
        File file = null;
        OutputStream os = null;
        HttpURLConnection httpUrl = null;
        try {
            httpUrl = (HttpURLConnection) new URL(url).openConnection();
            httpUrl.setConnectTimeout(300000);
            httpUrl.setReadTimeout(300000);
            httpUrl.setRequestProperty("Content-Length", "1000");
            httpUrl.connect();
            ins = httpUrl.getInputStream();
            file = new File(System.getProperty("java.io.tmpdir") + File.separator + "seat" + System.currentTimeMillis());
            if (file.exists()) {
                file.delete();
            }
            os = new FileOutputStream(file);
            int bytesRead;
            int len = 8192;
            byte[] buffer = new byte[len];
            while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            log.error("地址请求不可用或响应超时");
            e.printStackTrace();
        } finally {
            os.close();
            ins.close();
            if (httpUrl != null) {
                httpUrl.disconnect();
            }
        }
        return file;
    }

二.Word模板的制作

2.1 新建word文档,在需要替换变量位置的地方键盘Ctrl + F9,鼠标右击编辑域,选择邮件合并类型,输入"MERGEFIELD ${name}"

2.2 插入模板图片

插入图片书签,调整尺寸大小,方便变量替换

模板制作的基操基本如此,就不详细介绍了,这边的变量赋值的控制语言作者是使用的Freemarker,如需要复杂实现的可以百度了解下这个模板引擎的语句。这里作者提供一些常见的语句参考。

bash 复制代码
//1.判断catalogFirstList集合非空则遍历该集合,单实体使用别名catalog
MERGEFIELD @before-row[#if (catalogFirstList)??][#list catalogFirstList as catalog]
MERGEFIELD ${catalog.name!}
MERGEFIELD @after-row[/#list][/#if]

//2.if语句
MERGEFIELD [#if (notarize.purpose)??][#if notarize.purpose=='其它船舶']☑[#else]□[/#if][#else]□[/#if]

MERGEFIELD [#if shipownerType == '0']
MERGEFIELD [/#if]

//3.大于等于
MERGEFIELD [#if shipPicSize gte 1]

//4.大于
MERGEFIELD [#if shipPicSize > 0]

5.或运算
MERGEFIELD [#if shipowner.type == '1' || shipowner.type == '0']

6.时间格式化(防止非空报错)
MERGEFIELD [#if (record.takeOverTime)??]
MERGEFIELD ${record.takeOverTime?string('yyyy-MM-dd HH:mm:ss')}
MERGEFIELD [/#if]

7.单个变量防止空指针
MERGEFIELD ${notarize.name!}
相关推荐
所待.3831 小时前
JavaEE之线程初阶(上)
java·java-ee
郑祎亦2 小时前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
Theodore_102213 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
LIT-涛1 天前
JavaEE初学07
数据库·oracle·java-ee
&梧桐树夏1 天前
JavaEE 线程安全
java-ee·多线程
界面开发小八哥1 天前
「Java EE开发指南」如何使用Visual JSF编辑器设计JSP?(一)
java·ide·java-ee·编辑器·myeclipse
先睡1 天前
javaEE
java·java-ee
冷心笑看丽美人1 天前
Spring 框架七大模块(Java EE 学习笔记03)
学习·spring·架构·java-ee
郑祎亦1 天前
JavaWeb开发:HTML 页面与接口对接
前端·后端·java-ee·html
Theodore_10222 天前
7 设计模式原则之合成复用原则
java·开发语言·jvm·设计模式·java-ee·合成复用原则