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!}
相关推荐
JOJO___14 小时前
Spring IoC 配置类 总结
java·后端·spring·java-ee
蜗牛学苑_武汉14 小时前
设计模式之代理模式
java·网络·java-ee·代理模式
月临水15 小时前
JavaEE:网络编程(UDP)
java·网络·udp·java-ee
kakwooi16 小时前
JavaEE---Spring IOC(2)
java·spring·java-ee
奔强的程序16 小时前
【计算机毕业设计】医院电子病历
java-ee·毕业设计·课程设计·源代码管理
ZachOn1y21 小时前
Java 入门指南:JVM(Java虚拟机)—— 双亲委派模型(Parent Delegation Model)
java·jvm·后端·java-ee·团队开发·个人开发
·云扬·1 天前
Shiro框架
笔记·学习·java-ee
阿华的代码王国1 天前
【JavaEE】多线程编程引入——认识Thread类
java·开发语言·数据结构·mysql·java-ee
马剑威(威哥爱编程)1 天前
好用!推荐一个开源加密库 Bouncy Castle
java·安全·java-ee·bouncy castle
ZachOn1y1 天前
Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 新一代垃圾回收器 ZGC 收集器
java·开发语言·jvm·后端·java-ee·个人开发