当前位置: 首页 > article >正文

使用xdocreport导出word

之前java总用freemaker进行导出,但是改xml实在是太繁琐了,这次找了另一个工具进行体验.

一、简单导出

pom引入

 <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.core</artifactId><version>2.0.6</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.document</artifactId><version>2.0.6</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.template</artifactId><version>2.0.6</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.document.docx</artifactId><version>2.0.6</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId><version>2.0.6</version></dependency>

导出代码

public void genDoc() {RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;HttpServletResponse response = attributes.getResponse();try (InputStream inputStream = POICacheManager.getFile("template.docx")) {// 3. 读取模板,创建 IXDocReport 对象IXDocReport report = XDocReportRegistry.getRegistry().loadReport(inputStream, TemplateEngineKind.Freemarker);// 4. 创建上下文,设置变量(你可以按需扩展)IContext context = report.createContext();context.put("name", "张三");//编辑域代码 ctrl F9 类别选 邮件合并 域名mergefield 域代码后面填 ${name}// 设置响应头,准备输出 Word 文件response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");response.setHeader("Content-Disposition", "attachment; filename=generated-document.docx");// 5. 生成 Word 并写入响应输出流try (OutputStream out = response.getOutputStream()) {report.process(context, out);}} catch (Exception e) {log.error(">>> 生成 Word 失败:", e);// 手动返回错误信息try {response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);response.getWriter().write("生成文档失败:" + e.getMessage());} catch (Exception ex) {log.error(">>> 写回错误信息失败", ex);}}}

在resource目录新建word文件名为template.docx

打开template.docx

输入任意字符,然后 Ctrl+9插入域,然后右键编辑域,类别选 邮件合并 域名选mergefield 域代码后面填 ${name} 保存后用上面的代码导出

导出后可以看到域代码位置被填充为张三了。

二、进阶用法

1.动态表格行

分两种情况处理

(1)第一列为序号列

将第一列填充3个域  

"@before-row[#list productInfoList as item]" 
${item?index+1} 
@after-row[/#list] 

第二列 填充实际的字段即可

${item.name}

(2)第一列不序号列

将上文中的序号表达式${item?index+1} 换成你想填充的表达式,如

${item.code} 

其他处理跟上卖弄一样

在java中的定义,先定义实体,然后context.put即可

//假设之前定义了productInfo实体,实体有code name等字段
List<ProductInfo> productInfoList = new ArrayList();
...context.put("productInfoList", productInfoList );

2.图片

图片不用域,在要导入的地方插入一张图片,然后建立书签,建立书签的方法如下

选中文档中的某张图片,单击【插入】菜单下【链接】子菜单中的【书签】。

这里的书签名跟上面的域变量名类似

java代码

//根据文件读取
IImageProvider iImageProvider = new FileImageProvider(file, false);
context.put("pic", iImageProvider);//dataurlbase64的字符串,不含前缀
byte[] imageBytes = Base64.getDecoder().decode(base64Image);
//创建 ByteArrayImageProvider 实例
ByteArrayImageProvider imageProvider = new ByteArrayImageProvider(imageBytes, "png");
context.put("pic", imageProvider );

3.条件显示隐藏

使用if标签,下面是3个域

[#if data.ccUser??] 申请人:${data.ccUser } [/#if]

可以看到两个if标签域包裹了文字和变量

4.空值处理

空值直接使用会报错,可使用表达式

${tx.amount!}

或者

${tx.amount?if_exists}

上面表达式表示有值填充,无值不填充

5.单元格合并

实现起来比较复杂,在模板中先合并,然后对多列使用第一节的动态表格行基本上可以实现按层级合并,如果是跨列合并,比较复杂的合并目前还没找到好的解决方案?或许需要考虑原生freemaker或者poi-tl?

6.关键字

在实体中应尽量避免使用以下关键字

length 

http://www.lryc.cn/news/2403083.html

相关文章:

  • 青少年编程与数学 01-011 系统软件简介 05 macOS操作系统
  • Python打卡训练营学习记录Day43
  • 【Android基础回顾】二:handler消息机制
  • 每日Prompt:每天上班的状态
  • .net ORM框架dapper批量插入
  • C++11 右值引用:从入门到精通
  • .net 使用MQTT订阅消息
  • Python实现快速排序的三种经典写法及算法解析
  • 【递归、搜索与回溯】综合练习(四)
  • 强化学习入门:Gym实现CartPole随机智能体
  • STM32:CAN总线精髓:特性、电路、帧格式与波形分析详解
  • 贝叶斯深度学习!华科大《Nat. Commun.》发表BNN重大突破!
  • 【大模型LLM学习】Flash-Attention的学习记录
  • 三、元器件的选型
  • 精益数据分析(95/126):Socialight的定价转型启示——B2B商业模式的价格策略与利润优化
  • stm32_DMA
  • 物联网数据归档之数据存储方案选择分析
  • 【自动驾驶避障开发】如何让障碍物在 RViz 中‘显形’?呈现感知数据转 Polygon 全流程
  • 【C语言】C语言经典小游戏:贪吃蛇(上)
  • usbutils工具的使用帮助
  • vue2中使用jspdf插件实现页面自定义块pdf下载
  • 如何防止服务器被用于僵尸网络(Botnet)攻击 ?
  • 基于cornerstone3D的dicom影像浏览器 第二十九章 自定义菜单组件
  • 【Block总结】DBlock,结合膨胀空间注意模块(Di-SpAM)和频域模块Gated-FFN|即插即用|CVPR2025
  • 【学习笔记】单例类模板
  • 字符串加密(华为OD)
  • 口罩佩戴检测算法AI智能分析网关V4工厂/工业等多场景守护公共卫生安全
  • Double/Debiased Machine Learning
  • HarmonyOS Next 弹窗系列教程(4)
  • 【C】-递归