前文我们介绍了通过Apache POI通过来导出word的例子;那如果是word模板方式,有没有开源库通过模板方式导出word呢?poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性。本文主要介绍通过SpringBoot集成poi-tl实现模板方式的Word导出功能。

知识准备

需要理解文件上传和下载的常见场景和技术手段。@pdai

什么是poi-tl

如下内容来源于,poi-tl官网

poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档。

优势:

它还支持自定义插件,如下是官网代码仓库支持的特性

poi-tl supports custom functions (plug-ins), functions can be executed anywhere in the Word template, do anything anywhere in the document is the goal of poi-tl.

Feature Description
Text Render the tag as text
Picture Render the tag as a picture
Table Render the tag as a table
Numbering Render the tag as a numbering
Chart Bar chart (3D bar chart), column chart (3D column chart), area chart (3D area chart), line chart (3D line chart), radar chart, pie chart (3D pie Figure) and other chart rendering
If Condition Hide or display certain document content (including text, paragraphs, pictures, tables, lists, charts, etc.) according to conditions
Foreach Loop Loop through certain document content (including text, paragraphs, pictures, tables, lists, charts, etc.) according to the collection
Loop table row Loop to copy a row of the rendered table
Loop table column Loop copy and render a column of the table
Loop ordered list Support the loop of ordered list, and support multi-level list at the same time
Highlight code Word highlighting of code blocks, supporting 26 languages ​​and hundreds of coloring styles
Markdown Convert Markdown to a word document
Word attachment Insert attachment in Word
Word Comments Complete support comment, create comment, modify comment, etc.
Word SDT Complete support structured document tag
Textbox Tag support in text box
Picture replacement Replace the original picture with another picture
bookmarks, anchors, hyperlinks Support setting bookmarks, anchors and hyperlinks in documents
Expression Language Fully supports SpringEL expressions and can extend more expressions: OGNL, MVEL...
Style The template is the style, and the code can also set the style
Template nesting The template contains sub-templates, and the sub-templates then contain sub-templates
Merge Word merge Merge, you can also merge in the specified position
custom functions (plug-ins) Plug-in design, execute function anywhere in the document

poi-tl的TDO模式

TDO模式:Template + data-model = output

以官网的例子为例:

XWPFTemplate template = XWPFTemplate.compile("template.docx").render(
new HashMap<String, Object>(){{
put("title", "Hi, poi-tl Word模板引擎");
}});
template.writeAndClose(new FileOutputStream("output.docx"));
  • compile 编译模板 - Template
  • render 渲染数据 - data-model
  • write 输出到流 - output

Template:模板

模板是Docx格式的Word文档,你可以使用Microsoft office、WPS Office、Pages等任何你喜欢的软件制作模板,也可以使用Apache POI代码来生成模板。

所有的标签都是以{{开头,以}}结尾,标签可以出现在任何位置,包括页眉,页脚,表格内部,文本框等,表格布局可以设计出很多优秀专业的文档,推荐使用表格布局。

poi-tl模板遵循“所见即所得”的设计,模板和标签的样式会被完全保留。

Data-model:数据

数据类似于哈希或者字典,可以是Map结构(key是标签名称):

Map<String, Object> data = new HashMap<>();
data.put("name", "Sayi");
data.put("start_time", "2019-08-04");

可以是对象(属性名是标签名称):

public class Data {
private String name;
private String startTime;
private Author author;
}

数据可以是树结构,每级之间用点来分隔开,比如{ {author.name} }标签对应的数据是author对象的name属性值。

Word模板不是由简单的文本表示,所以在渲染图片、表格等元素时提供了数据模型,它们都实现了接口RenderData,比如图片数据模型PictureRenderData包含图片路径、宽、高三个属性。

Output:输出

以流的方式进行输出:

template.write(OutputStream stream);

可以写到任意输出流中,比如文件流:

template.write(new FileOutputStream("output.docx"));

比如网络流:

response.setContentType("application/octet-stream");
response.setHeader("Content-disposition","attachment;filename=\""+"out_template.docx"+"\""); // HttpServletResponse response
OutputStream out = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
template.write(bos);
bos.flush();
out.flush();
PoitlIOUtils.closeQuietlyMulti(template, bos, out); // 最后不要忘记关闭这些流。

实现案例

这里展示SpringBoot集成poi-tl基于word模板导出Word, 以及导出markdown为word的例子。

Pom依赖

引入poi的依赖包

基础的包:

<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.0</version>
</dependency>

插件的包如下,比如highlight,markdown包

<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl-plugin-highlight</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl-plugin-markdown</artifactId>
<version>1.0.3</version>
</dependency>

导出基于template的word

controller中的方法

@ApiOperation("Download Word")
@GetMapping("/word/download")
public void download(HttpServletResponse response) {
try {
XWPFTemplate document = userService.generateWordXWPFTemplate();
response.reset();
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition",
"attachment;filename=user_word_" + System.currentTimeMillis() + ".docx");
OutputStream os = response.getOutputStream();
document.write(os);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Service中的实际方法

@Override
public XWPFTemplate generateWordXWPFTemplate() throws IOException {
Map<String, Object> content = new HashMap<>();
content.put("title", "Java 全栈知识体系");
content.put("author", "pdai");
content.put("site", new HyperlinkTextRenderData("https://pdai.tech", "https://pdai.tech")); content.put("poiText", "Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。更多请参考[官方文档](https://poi.apache.org/index.html)"); content.put("poiText2", "生成xls和xlsx有什么区别?POI对Excel中的对象的封装对应关系?");
content.put("poiList", Numberings.create("excel03只能打开xls格式,无法直接打开xlsx格式",
"xls只有65536行、256列; xlsx可以有1048576行、16384列",
"xls占用空间大, xlsx占用空间小,运算速度也会快一点")); RowRenderData headRow = Rows.of("ID", "Name", "Email", "TEL", "Description").textColor("FFFFFF")
.bgColor("4472C4").center().create();
TableRenderData table = Tables.create(headRow);
getUserList()
.forEach(a -> table.addRow(Rows.create(a.getId() + "", a.getUserName(), a.getEmail(), a.getPhoneNumber() + "", a.getDescription())));
content.put("poiTable", table); Resource resource = new ClassPathResource("pdai-guli.png");
content.put("poiImage", Pictures.ofStream(new FileInputStream(resource.getFile())).create()); return XWPFTemplate.compile(new ClassPathResource("poi-tl-template.docx").getFile()).render(content);
} private List<User> getUserList() {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
userList.add(User.builder()
.id(Long.parseLong(i + "")).userName("pdai" + i).email("pdai@pdai.tech" + i).phoneNumber(121231231231L)
.description("hello world" + i)
.build());
}
return userList;
}

准备模板

导出word

导出markdown为word

controller中的方法

@ApiOperation("Download Word based on markdown")
@GetMapping("/word/downloadMD")
public void downloadMD(HttpServletResponse response) {
try {
XWPFTemplate document = userService.generateWordXWPFTemplateMD();
response.reset();
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition",
"attachment;filename=user_word_" + System.currentTimeMillis() + ".docx");
OutputStream os = response.getOutputStream();
document.write(os);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Service中实现的方法


@Override
public XWPFTemplate generateWordXWPFTemplateMD() throws IOException {
MarkdownRenderData code = new MarkdownRenderData(); Resource resource = new ClassPathResource("test.md");
code.setMarkdown(new String(Files.readAllBytes(resource.getFile().toPath())));
code.setStyle(MarkdownStyle.newStyle()); Map<String, Object> data = new HashMap<>();
data.put("md", code); Configure config = Configure.builder().bind("md", new MarkdownRenderPolicy()).build(); return XWPFTemplate.compile(new ClassPathResource("markdown_template.docx").getFile(), config).render(data);
}

准备模板

导出word

示例源码

https://github.com/realpdai/tech-pdai-spring-demos

参考文章

http://deepoove.com/poi-tl/

更多内容

告别碎片化学习,无套路一站式体系化学习后端开发: Java 全栈知识体系(https://pdai.tech)

SpringBoot集成文件 - 如何基于POI-tl和word模板导出庞大的Word文件?的更多相关文章

  1. java根据word模板导出word文件

    1.word模板文件处理,如下图所示在word 文档中填值的地方写入占位变量 2.将word文档另存为xml文件.编辑如下图,找到填写的占位,修改为${bcrxm}格式 3.将文件后缀名改为.ftl文 ...

  2. 利用模板导出文件(二)之jacob利用word模板导出word文件(Java2word)

    https://blog.csdn.net/Fishroad/article/details/47951061?locationNum=2&fps=1 先下载jacob.jar包.解压后将ja ...

  3. SpringBoot集成WebSocket【基于纯H5】进行点对点[一对一]和广播[一对多]实时推送

    代码全部复制,仅供自己学习用 1.环境搭建 因为在上一篇基于STOMP协议实现的WebSocket里已经有大概介绍过Web的基本情况了,所以在这篇就不多说了,我们直接进入正题吧,在SpringBoot ...

  4. SpringBoot集成WebSocket【基于STOMP协议】进行点对点[一对一]和广播[一对多]实时推送

    原文详细地址,有点对点,还有广播的推送:https://blog.csdn.net/ouyzc/article/details/79884688 下面是自己处理的一些小bug 参考原文demo,结合工 ...

  5. 一个基于POI的通用excel导入导出工具类的简单实现及使用方法

    前言: 最近PM来了一个需求,简单来说就是在录入数据时一条一条插入到系统显得非常麻烦,让我实现一个直接通过excel导入的方法一次性录入所有数据.网上关于excel导入导出的例子很多,但大多相互借鉴. ...

  6. PHP导出excel文件,第一步先实现PHP模板导出不带数据

    今天继续研究PHP导出excel文件,把复杂的事情简单化,一步步实现功能,首先实现模板文件的导出,随后再实现写入数据后导出,最终实现功能,这是基本思路.中间可以加一步,先自己写入数据导出试试,随后再数 ...

  7. (解决)easypoi模板导出多个excel文件并压缩

    目录 easypoi版本--3.1.0 实现代码 后语 easypoi版本--3.1.0 实现代码 public void export(HttpServletResponse response, H ...

  8. php根据word模板生成新的word文件

    原文地址:http://www.niu12.com/article/16 php使用phpword将word内容变量替换 a.安装phpword composer require phpoffice/ ...

  9. PHP导出数据到CSV文件函数/方法

    如果不清楚什么是CSV文件,可看如下文章介绍  CSV格式的是什么文件?CSV是什么的缩写? /** * 导出数据到CSV文件 * @param array $data 数据 * @param arr ...

随机推荐

  1. 试驾 Citus 11.0 beta

    https://www.citusdata.com/blog/2022/03/26/test-drive-citus-11-beta-for-postgres/ Citus 11.0 beta 的最大 ...

  2. 场景实践:使用RDS和ECS搭建个人博客

    体验简介 本教程将使用一台基础环境为CentOS7.7的云服务器ECS实例, 搭配您已有的云数据库RDS实例,帮助您快速搭建属于自己的云上博客. 背景知识 本场景主要涉及以下云产品和服务: 阿里云关系 ...

  3. Oracle数据库丢失表排查思路

    Oracle数据库丢失表排查思路 说明:由于系统采用ID取模分表法进行Oracle数据存储,某日发现Oracle数据库中缺少对应的几张业务数据表,遂进行相关问题查询,简单记录一下排查思路: 由于我们代 ...

  4. “摆地摊“都找不到全栈工程师?JNPF帮你分分钟搞定!

    大街上捕捉野生程序员 都这样了还找不到全栈工程师 全栈工程师(Full-Stack Engineer)图鉴: 全栈工程师,也叫全端工程师(同时具备前端和后台能力),英文Full Stack  deve ...

  5. LOJ数列分块 9 题解

    \(1.\) 题意 给定一个长度 \(n\) 序列,每次查询区间 \(l, r\) 的众数. \(2.\) 思路 如果边界是 \([l,r]\),\(l\) 在第 \(a\) 块,\(r\) 在第 \ ...

  6. Java 基础常见知识点&面试题总结(上),2022 最新版!| JavaGuide

    你好,我是 Guide.秋招即将到来,我对 JavaGuide 的内容进行了重构完善,公众号同步一下最新更新,希望能够帮助你. 基础概念与常识 Java 语言有哪些特点? 简单易学: 面向对象(封装, ...

  7. zigbee技术数传电台在石油探井状态监测系统

    石油探井分布分散,数量众多,出现异常现象需及时处理.人工巡视耗时长.时效性差:有线传输存在布线繁琐.成本高.现场无移动网络覆盖等诸多缺点. 现需要一种支持大量接入.覆盖范围广.数据传输高效且有数据中心 ...

  8. 【Openxml】颜色变化属性计算

    Openxml的颜色变化属性 目前Openxml存在颜色变化属性如下: 参数 说明 Hue 色调(色相) HueModulate 色调调制,百分比 HueOffset 色调偏移量,角度值 Satura ...

  9. 树莓派开发笔记(十七):树莓派4B+上Qt多用户连接操作Mysql数据库同步(单条数据悲观锁)

    前言   安装了mysq数据库,最终时为了实现在一个树莓派上实现多用户多进程操作的同步问题,避免数据并发出现一些错误,本篇安装了远程服务并且讲述了使用Qt进行悲观锁for update操作,命令行进行 ...

  10. kubernetes之常用核心资源对象

    部门产品线本身是做DEVOPS平台,最近部署架构也在往K8S上靠了,不得不学一下K8S.自己搭建了K8S集群与harbor仓库来学习. 1.kubernetes之常用核心资源对象 1.1.K8s服务部 ...