文章首发于我的博客:Java怎样实现将数据导出为Word文档 - Liu Zijian's Blog

我们在开发一些系统的时候,例如OA系统,经常能遇到将审批单数据导出为word和excel文档的需求,导出为excel是比较简单的,因为excel有单元格来供我们定位数据位置,但是word文档的格式不像表格那样可以轻松的定位,要想将数据导出为一些带有图片和表格的这种结构复杂的word文档该怎样实现呢。

poi-tl [1]是一款可以帮助我们实现这种功能的Java开源项目,它把POI和Freemarker相结合,可以基于我们绘制好的word文档模板来填充数据进去,然后生成新的word文档。poi-tl托管在GitHub:https://github.com/Sayi/poi-tl

例如,我们要生成一个差旅行程单,首先要绘制这样的一个word文档模板,用{{name}}代表姓名进行占位,姓名就是普通文字类型,以此类推。tripList作为渲染行程表格的数据源的名字,是ArrayList集合类型,放在表格的表头,用[from]表示tripList集合中每个元素的from属性的值,渲染到当前行的某一列上,以此类推。最后的三个签署对应的是领导的签名笔迹图片,图片类型要用变量名前多一个@的形式{{@****Pin}}来表示

如果表格中某一列是图片,则表示为[@变量]

模板绘制好以后,开始使用poi-tl工具生成word文档,首先新建maven项目,引入poi-tl的依赖和需要的其他依赖,然后将这个绘制好的word模板文件放在工程的根目录

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId>
<artifactId>poi-tl</artifactId>
<version>1.0-SNAPSHOT</version> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <dependencies>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies> </project>

然后,新建一个Entity类: org.example.TravelApplyExportVO

package org.example;

import com.deepoove.poi.data.PictureRenderData;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; import java.util.ArrayList;
import java.util.List; @Data
@AllArgsConstructor
@NoArgsConstructor
public class TravelApplyExportVO {
private String no;
private String name;
private String dept;
private String employeeNo;
private String start;
private String end;
private String days;
private String address;
private String reason;
/**
* com.deepoove.poi.data.PictureRenderData 代表图片
*/
private PictureRenderData applyPin;
private PictureRenderData bossPin;
private PictureRenderData leaderPin; private String date; /**
* 用于渲染表格的集合
*/
private List<Route> tripList = new ArrayList<>(); @Data
@AllArgsConstructor
@NoArgsConstructor
public static class Route {
private String from;
private String to;
private String flight;
private String depTime;
private String arrTime;
private String cabin;
}
}

新建测试类: org.example.Main,用poi-tl组件基于刚刚绘制的word模板生成一个差旅行程单

package org.example;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import lombok.SneakyThrows; import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList; public class Main { @SneakyThrows
public static void main(String[] args) { TravelApplyExportVO vo = new TravelApplyExportVO();
vo.setNo("202500001");
vo.setName("lzj");
vo.setDept("技术部");
vo.setEmployeeNo("00000001");
vo.setStart("2025-01-01");
vo.setEnd("2025-02-01");
vo.setDays("30");
vo.setAddress("中国香港");
vo.setReason("系统维护"); // 在项目根路径读取笔迹图片,并设置大小
PictureRenderData data1 = Pictures.ofBytes(Files.readAllBytes(Paths.get("img2.png")))
.size(120, 60)
.create(); PictureRenderData data2 = Pictures.ofBytes(Files.readAllBytes(Paths.get("img.png")))
.size(120, 60)
.create(); PictureRenderData data3 = Pictures.ofBytes(Files.readAllBytes(Paths.get("img.png")))
.size(120, 60)
.create(); vo.setApplyPin(data1 );
vo.setBossPin( data2);
vo.setLeaderPin( data3); vo.setDate("2025-01-10"); // 行程List,最终渲染到文档的表格中
vo.setTripList(new ArrayList<TravelApplyExportVO.Route>() {
{
add(new TravelApplyExportVO.Route("BJX","ZQZ","ZH5643","2025-01-01 15:00","2025-01-01 16:00","E"));
add(new TravelApplyExportVO.Route("ZQZ","CDE","JUH6532","2026-01-01 15:00","2025-12-01 16:00","A"));
add(new TravelApplyExportVO.Route("BJX","ZQZ","KJU0954","2027-01-01 15:00","2025-05-01 16:00","Q"));
}
}); LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); // !!将tripList通过表格来渲染
Configure config = Configure.builder()
.bind("tripList", policy)
.build(); XWPFTemplate template = XWPFTemplate
.compile("模板.docx", config)
.render(vo); template.writeAndClose(Files.newOutputStream(Paths.get("output.docx")));
}
}

然后领导签名笔记图片素材img.png,img2.png也需要放进工程根目录下

都完成后,执行main()方法测试,程序运行结束后,将在根路径生成文件output.docx,打开就是我们想要的效果了。

文章写到这已经是深夜了,最新在开发一个OA系统,需要Word导出的场景很多,由于之前没怎么接触过,于是熬夜攻关了一下并记录了下来,接下来希望项目能顺利交付吧~

参考


  1. https://deepoove.com/poi-tl/

Java怎样实现将数据导出为Word文档的更多相关文章

  1. javadoc导出成word文档

    刚刚上次弄完了一个坑爹的任务,这次我领导又给我一个让人脑瓜子疼的任务了. 基本上客户他在验收我们系统的时候,都会要求我们编写相关的文档,这次也不例外. 只是这次的客户要求我们给出接口文档.不仅是要整个 ...

  2. PowerDesigner将PDM导出生成WORD文档

    PowerDesigner将PDM导出生成WORD文档 环境 PowerDesigner15 1.点击Report Temlates 制作模板 2.如果没有模板,单击New图标创建.有直接双击进入. ...

  3. 将HTML导出生成word文档

    前言: 项目开发中遇到了需要将HTML页面的内容导出为一个word文档,所以有了这边随笔. 当然,项目开发又时间有点紧迫,第一时间想到的是用插件,所以百度了下.下面就介绍两个导出word文档的方法. ...

  4. (转)WEB页面导出为Word文档后分页&横向打印的方法

    <html>    <HEAD>        <title>WEB页面导出为Word文档后分页&横向打印的方法 </title>    < ...

  5. 网页导出成word文档的默认视图方式问题

    网页导出成word文档的默认视图方式问题 一般保存后的word文档默认是“Web版式视图”打开,这样会给客户的感觉不是真正的word文档,必须实现打开就是“页面视图” 1. 修改<html> ...

  6. 可以把思维导图导出为word文档方便其他人查看吗?

    MindManager除了强大的大纲视图编辑功能外,还拥有多种导出格式,方便大家迅速导出文件,在团队中分享自己的观点,提高团队的工作效率,本次小编使用的思维导图软件版本是MindManager 202 ...

  7. Java中用Apache POI生成excel和word文档

    概述: 近期在做项目的过程中遇到了excel的数据导出和word的图文表报告的导出功能.最后决定用Apache POI来完毕该项功能.本文就项目实现过程中的一些思路与代码与大家共享.同一时候.也作为自 ...

  8. 如何在PowerDesigner将PDM导出生成WORD文档或者html文件

    a)         使用PowerDesigner打开pdm文件 b)         点击Report Temlates 制作模板 点击PowerDesigner菜单栏“Report” -> ...

  9. PowerDesigner将PDM导出生成WORD文档--温习老知识

    转:http://www.cnblogs.com/wudiwushen/archive/2010/05/13/1734812.html 今天的温习老知识,是如何将一个PD设计的PDM来导出WORD文档 ...

  10. Java Web项目中使用Freemarker生成Word文档

    Web项目中生成Word文档的操作屡见不鲜.基于Java的解决方式也是非常多的,包含使用Jacob.Apache POI.Java2Word.iText等各种方式,事实上在从Office 2003開始 ...

随机推荐

  1. zinxV0.1

    基础的server 框架 抽象层IServer.go IServer.go type IServer interface { // 实现一个服务器的基本三个接口,启动,停止,入口 Start() St ...

  2. 《Django 5 By Example》阅读笔记:p237-p338

    <Django 5 By Example>学习第11天,p237-p338总结,总计102页. 一.技术总结 1.follow system(关注功能) 表之间的关系有三种:OneToOn ...

  3. 一、FreeRTOS学习笔记-基础知识

    一基础知识 1.任务调度(调度器) 调度器就是使用相关的调度算法来决定当前需要执行的哪个任务 FreeRTOS三种任务调度方式: 1.抢占式调度:主要是针对优先级不同的任务,每个任务都有一个优先级,优 ...

  4. Git之message提交

    作用 编写格式化的 commit message 能够大大提高代码的维护效率. 比如: 可以提供更多的历史信息,方便快速浏览: 可以过滤某些 commit(比如文档改动),便于快速查找信息: 可以直接 ...

  5. rsync之实战

    简介 rsync是远程(或本地)复制和同步文件最常用的命令. 借助rsync命令,你可以跨目录,跨磁盘和跨网络远程与本地数据进行复制和同步.举例来说:在两台Linux主机之间进行数据备份和镜像.本文介 ...

  6. Tailwind CSS样式优先级控制

    前情 Tailwind CSS 是一个原子类 CSS 框架,它将基础的 CSS 全部拆分为原子级别,能达到最小化项目CSS.它的工作原理是扫描所有 HTML 文件.JavaScript 组件以及任何模 ...

  7. 服务拆分之《Dubbo服务跨云通信》

    2022年10月开始,公司从阿里请来的架构师将全力推进服务拆分这个计划.实际上这个计划早就提上日程了,只是没有一个带头大哥带着把这个事情搞起来,因为这个系统太庞大了,还非常的复杂,当时就没有哪一个人是 ...

  8. VTK 视角的旋转、平移、缩放

    在CAD/CAM软件中,都需要旋转.平移和缩放视角,来观察操作图形.由于VTK定义的交互的类型不是很适用,所有通过定义一套自己的交互方式. 在下面代码中,鼠标左键平移,滚轮缩放,右键旋转. 先定义一个 ...

  9. 源启行业AI平台 银行智能业务的驱动引擎

    AI技术已经深入金融行业,在营销.渠道.风控等领域广泛应用,但人工智能开发与应用面临成本高.难度大.门槛高.重复建设.无统一管理复用AI模型资产等问题,这些问题也正是源启AI行业平台要解决的. 源启行 ...

  10. 渗透测试-前端加密分析之RSA加密登录(密钥来源服务器)

    本文是高级前端加解密与验签实战的第6篇文章,本系列文章实验靶场为Yakit里自带的Vulinbox靶场,本文讲述的是绕过RSA加密来爆破登录. 分析 这里的代码跟上文的类似,但是加密的公钥是通过请求服 ...