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!}
相关推荐
Wlq041533 分钟前
J2EE平台
java·java-ee
XiaoLeisj40 分钟前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee
阑梦清川42 分钟前
JavaEE初阶---网络原理(五)---HTTP协议
网络·http·java-ee
杨荧2 小时前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
XiaoLeisj13 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
尢词17 小时前
SpringMVC
java·spring·java-ee·tomcat·maven
阑梦清川20 小时前
JavaEE进阶---第一个SprintBoot项目创建过程&&&我的感受
java·java-ee·springboot
移民找老国21 小时前
加拿大移民新风向
java-ee·maven·phpstorm·visual studio code·nio
琪露诺大湿1 天前
JavaEE-多线程初阶(4)
java·开发语言·jvm·java-ee·基础·1024程序员节·原神