XDocReport文书生成总结

news2025/1/24 14:44:42

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

一.XDocReport技术Java实现

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

 //获取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();
}

    /**
     * 将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,如需要复杂实现的可以百度了解下这个模板引擎的语句。这里作者提供一些常见的语句参考。

//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!}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/894685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring-3-Spring AOP概念全面解析

今日目标 能够理解AOP的作用 能够完成AOP的入门案例 能够理解AOP的工作流程 能够说出AOP的五种通知类型 一、AOP 1 AOP简介 思考:什么是AOP,AOP的作用是什么? 1.1 AOP简介和作用【理解】 AOP(Aspect Oriented Programming)面向切面编程,一…

Windows系统修改域名DNS指向两种方式

一、直接打开对应文件进行修改 1、进入hosts文件目录:C:\Windows\System32\drivers\etc 2、右键打开HOSTS文件进行编辑,将需要对应的域名和IP地址进行配置 编写完成后 Ctrl s 进行保存即可。 二、使用DOS命令进行修改 1、按住键盘win键 r 打开命令…

设计师必备的5个PNG免抠素材网站,简直不要太好用~

广大设计师们是不是经常要用免抠素材的时候网上找的质量差,还要各种付费才能使用,最后只能打开PS慢慢的扣,真的很费时间。本期我就给大家推荐5个高质量、免费的免抠素材网站,有需要的朋友们赶紧收藏。 菜鸟图库 https://www.suc…

2021年3月全国计算机等级考试真题(C语言二级)

2021年3月全国计算机等级考试真题(C语言二级) 第1题 算法空间复杂度的度量方法是() A. 算法程序的长度 B. 算法所处理的数据量 C. 执行算法所需要的工作单元 D. 执行算法所需要的存储空间 正确答案:D 第2题 下列叙…

wangEditor修改节点数据

前言 wangEditor简介 wangEditor 是一款基于 JavaScript 和 jQuery 的开源富文本编辑器,具有简单易用、功能丰富的特点。它提供了一整套的富文本编辑功能,包括文字样式设置、插入图片、插入表格、插入链接、代码块等。wangEditor 支持多种浏览器&#x…

大数据时代下的数据中心运维管理

摘要:本文将从数据中心运维管理的角度,联系现实情况,对运维管理进行研究,期望通过本项目的研究,显著提升数据中心运维治理的整体质量。这样,才能充分发挥大数据的价值,并推动企业加速发展。 关…

将nginx内存池代码单独编译运行,了解nginx内存池工作原理,附代码

初识nginx——内存池篇 https://www.cnblogs.com/magicsoar/p/6040238.html 为了自身使用的方便,Nginx封装了很多有用的数据结构,比如ngx_str_t ,ngx_array_t, ngx_pool_t 等等,对于内存池,nginx设计的十分精炼,值得我…

揭秘亚马逊广告运作:了解逻辑,事半功倍的广告成功!

亚马逊广告的多重形式亚马逊为卖家提供了多种广告形式,用于在平台上展示并推广产品。以下是亚马逊广告的主要形式: 1.Sponsored Products: 这是常见的广告类型,允许产品在搜索结果和产品页面中显示。广告与自然搜索结果相似&…

23款奔驰GLE450豪华型桃木方向盘,提升方向盘握感

桃木是目前国内各级车型中最为主流的木饰,虽然看起来一样,但是多数低端车型中配备的并非实木,而是由聚酯材料制成的仿桃木。其实我们这里所说的“桃木”也并非我们所熟知的那个可以结桃子的果树,而是胡桃木或是核桃木。胡桃木原产…

算法通关村第八关——轻松搞定翻转二叉树

二叉树有很多经典算法题,今天我们就来看一下二叉树里的翻转问题。 力扣226,给了一棵二叉树,要将二叉树整体翻转。 分析:观察图中翻转前后的二叉树,我们不难发现,翻转过程中,只需要把每一个节点的左右子节点…

13. Vuepress2.x 部署站点的基础路径从配置文件中读取

收到需求,站点要部署到 非根路径 下,且将来会根据 版本号 区分不同的基础路径。需要从统一的文件中读取,方便其它 js 文件和 config.js 配置统一读取。 目录 docs\.vuepress\public\cfg\ 下新建文件 version.js,内容如下 const P…

cmake扩展(5)——file命令排除部分文件

在cmake中可以使用file命令获取需要的文件&#xff0c;并且支持正则/通配符&#xff0c;使用起来还是很方便的。 #语法file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...])#example file(GLOB_RECURSE SOURCES "src/*.h" "src/*.cp…

如何计算 SDK 占用的 CPU 算力值(DMIPS)

什么是 DMIPS &#xff1f; 网上搜了些 DMIPS 的相关材料&#xff0c;知道它是用来评价 CPU 运算能力的一个指标。其中在知乎上有人介绍这个概念&#xff0c;是自动驾驶芯片性能常用的评价指标&#xff08;自动驾驶芯片性能评价指标:DMIPS,TOPS - 知乎&#xff09;。 如何计算…

CSS如何将浏览器文字设置小于12px

CSS如何将浏览器文字设置小于12px 使用transform: scale进行缩放 transform: scale(0.8);<div><p class"first">第一段文字</p><p class"second">第二段文字</p> </div>.first {font-size: 12px; }.second {font-si…

SeleniumIDE用例录制

1、录制回放方式的稳定性和可靠性有限 2、只支持 Firefox、Chrome 3、对于复杂的页面逻辑其处理能力有限 环境准备 Chrome 插件&#xff1a;https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd Firefox 插件&#xff1a;Selenium IDE …

Java课题笔记~ SpringBoot简介

1. 入门案例 问题导入 SpringMVC的HelloWord程序大家还记得吗&#xff1f; SpringBoot是由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化Spring应用的初始搭建以及开发过程 原生开发SpringMVC程序过程 1.1 入门案例开发步骤 ①&#xff1a;创建新模块&#…

==和equals方法之间的区别,hashcode的理解

==和equals方法之间的区别 字符串有字符串常量池的概念,本身就推荐使用String s="字符串", 这种形式来创建字符串对象, 而不是通过new关键字的方式, 因为可以把字符串缓存在字符串常量池中,方便下次使用,不用遇到new就在堆上开辟一块新的空间 有一对双胞胎姐妹,晓苑…

[bug] 记录version `GLIBCXX_3.4.29‘ not found 解决方法

在使用mediapipe 这个库的时候&#xff0c;首次使用出现 GLIBCXX_3.4.29’ not found 错误&#xff0c; 看起来是安装mediapipe 的时候自动升级了 matplotlib 这个库&#xff0c;导致依赖的 libstd.so 版本不满足了&#xff0c;GLIBCXX_3.4.29 is an object from libstdc.so.…

万宾燃气管网监测解决方案,守护城市生命线安全

方案背景 城市燃气管网作为连接天然气长输管线与天然气用户的桥梁&#xff0c;担负着向企业和居民用户直接供气的重要职责。随着城市燃气需求的急剧增加&#xff0c;城市燃气管网规模日趋庞大&#xff0c;安全隐患和风险也随之增加。目前&#xff0c;我国燃气管网的运行仍存在…

spad芯片学习总结

一、时间相关单光子计数法TCSPC(Time correlated single photon counting) 1> 如果spad接收用单次发射、峰值检测会怎么样 首先spad是概率性触发的器件&#xff0c;探测到的概率远小于1&#xff0c;而且不仅接收信号的光子可以触发&#xff0c;环境光噪声一样会被spad接收到…