poi-tl 生成 word 文件(插入文字、图片、表格、图表)

文章说明

本篇文章主要通过代码案例的方式,展示 poi-tl 生成 docx 文件的一些常用操作,主要涵盖以下内容 :

  • 插入文本字符(含样式、超链接)
  • 插入图片
  • 插入表格
  • 引入标签(通过可选文字的方式,这种方式也可以实现插入图片和插入表格)

当然 poi-tl 官方也有很详细的介绍,官网文档地址:https://deepoove.com/poi-tl/

项目初始化【必读】

项目创建好之后第一件事当然是引入依赖啦。

下面是 maven 引入的依赖,如果使用 Gradle 自行转成 Gradle 依赖。

<!-- poi 依赖 -->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>5.2.5</version>
</dependency>
<!-- poi-tl -->
<dependency>
  <groupId>com.deepoove</groupId>
  <artifactId>poi-tl</artifactId>
  <version>1.12.2</version>
</dependency>

在 poi-tl 生成 docx 文件时,先搞清楚三个问题:

  1. 定义 docx 模板文件:要生成怎么样的文件,自行创建一个 docx 的模板文件
  2. 定义模板文件的数据:向模板文件中,添加数据
  3. 生成文件位置:实际开发中大多会通过网络的方式传递,这里只展示生成在本地文件

本篇文章展示一些关键代码,为了减少冗余,我们可以定义一个生成 docx 的工具类 PoitlUtils:

import com.deepoove.poi.XWPFTemplate;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

/**
 * @author 17279
 */
public class PoitlUtils {

  /**
    * @param templateData 生成模板文件所需的所有数据
    * @param templateFilePath 模板文件路径(这里读取的是 resources 下的文件)
    * @param outputFilePath 模板文件输入的地址
    */
  public static void generateWordFile(Map<String, Object> templateData, String templateFilePath, String outputFilePath) {
    // 读取模板文件
    try (InputStream templateIn = PoitlUtils.class.getResourceAsStream(templateFilePath)) {
      // 生成模板文件
      XWPFTemplate template = XWPFTemplate.compile(templateIn).render(templateData);
      template.writeAndClose(new FileOutputStream(outputFilePath));
      // 这个目的是:生成文件之后调用 cmd 打开本地文件,实际生产不需要该操作
      // Runtime.getRuntime().exec(String.format("cmd /c %s", outputFilePath));
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

这里使用的所有 docs 模板文件,我都存放在 resources 的目录下。

在这里插入图片描述

插入文本

str_demo.docx 文件,文本使用 {{xxx}} 设置占位符:

{{str1}}	
{{str2}}
{{str3}}
{{str4}}
{{?strArr1}}{{=#this}} {{/strArr1}}

案例代码:

// 模板文件
String templateFilePath = "/word_template/str_demo.docx";
// 输出文件
String outputFilePath = "D:/output.docx";
// 插入文本数据
Map<String, Object> templateData = new HashMap<String, Object>() {{
  // 直接插入 String
  put("str1", "直接插入 String");
  // 插入含有样式的文本
  put("str2", Texts.of("插入含有样式的文").color("ff0000").create());
  // 插入含超链接的文本
  put("str3", Texts.of("插入含有样式的文").link("http://www.shijialeya.top/").create());
  // 传入一个对象
  put("str4", Arrays.asList("键盘敲破", "工资过万"));
  // 遍历文本
  put("strArr1", Arrays.asList("派大星", "瘸老板", "海绵宝宝", "章鱼哥", "蟹老板"));
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);

文档效果:

在这里插入图片描述

要注意 docx 文件上的 {{xxx}} xxx 的前后不要有空格,如果将外面的文字复制到 word 可能会自动加空格。

插入图片

img_demo.docx 文件,图片通过 {{@xxx}} 设置占位符:

{{@img1}}

{{@img2}}

{{@img3}}

{{@img4}}

{{?imgArr1}}{{@#this}}  {{/imgArr1}}

案例代码:

// 模板文件
String templateFilePath = "/word_template/img_demo.docx";
// 输出文件
String outputFilePath = "D:/output.docx";
// 插入文本数据
Map<String, Object> templateData = new HashMap<String, Object>() {{
  // 直接插入本地图片(默认图片的宽度与文档的宽度一致)
  // put("img1", "C:/Users/17279/Pictures/head.jpg");
  // 插入本地图片,并设置图片大小
  put("img1", Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
  // 通过流的形式写入图片
  put("img2", Pictures.ofStream(new FileInputStream("C:/Users/17279/Pictures/head.jpg"), PictureType.JPEG).size(150, 150).create());
  // 写入网络图片
  put("img3", Pictures.ofUrl("http://file.shijialeya.top/head.jpg", PictureType.JPEG).size(170, 170).create());
  // 写入通过 Java 生成的图片
  put("img4", Pictures.ofBufferedImage(new BufferedImage(190, 190, BufferedImage.TYPE_BYTE_GRAY), PictureType.PNG).size(190, 190).create());

  // 遍历图片
  put("imgArr1", new ArrayList<Object>() {{
    add(Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
    add(Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
    add(Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").size(100, 100).create());
  }});
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);

文档效果:

在这里插入图片描述

插入表格

tab_demo.docx 文件,图片通过 {{#xxx}} 设置占位符:

{{#tab1}}

{{#tab2}}

{{#tab3}}

合同名称	{{tab4.contractName}}
合同时间	{{tab4.contractDate}}	合同金额	{{tab4.money}}
合同公司	{{tab4.company}}

在这里插入图片描述

案例代码:

// 模板文件
String templateFilePath = "/word_template/tab_demo.docx";
// 输出文件
String outputFilePath = "D:/output.docx";
// 插入文本数据
Map<String, Object> templateData = new HashMap<String, Object>() {{
  // 插入一个基础表格
  String[][] tabData1 = {
    new String[]{"姓名", "性别", "年龄"},
    new String[]{"派大星", "16", "男"},
    new String[]{"章鱼哥", "35", "男"}
  };
  put("tab1", Tables.of(tabData1).create());

  // 插入一个含有样式的表格
  Tables.TableBuilder tabData2 = Tables
    // 创建一个指定宽度的表格(docx 文档的 80% 宽度)
    .ofPercentWidth("80%")
    // 表格设为水平居中
    .center()
    // 设置表格边框
    .border(BorderStyle.builder()
            // 边框样式
            .withType(XWPFTable.XWPFBorderType.DOUBLE)
            // 边框颜色
            .withColor("ff0000")
            // 边框粗细(边框为线条类型才会有效)
            .withSize(12)
            .build()
           );
  tabData2.addRow(Rows.of("姓名", "性别", "年龄")
                  // 设置文字颜色
                  .textColor("FFFFFF")
                  // 设置对应表格的背景颜色
                  .bgColor("4472C4")
                  // 文字居中
                  .center()
                  .create()
                 );
  tabData2.addRow(Rows.of("派大星", "16", "男").create());
  put("tab2", tabData2.create());

  // 合并单元格
  String[][] tabData3 = {
    new String[]{"姓名", "性别", "年龄"},
    new String[]{"派大星", "16", "男"},
    new String[]{"章鱼哥", "35", "男"},
    new String[]{"共2人", null, null},
  };
  put("tab3", Tables.of(tabData3)
      // 添加单元格合并规则
      .mergeRule(MergeCellRule
                 .builder()
                 // [纵坐标, 横坐标] 索引从零开始,合并 [3, 0] 到 [3, 2] 位置的表格
                 .map(MergeCellRule.Grid.of(3, 0), MergeCellRule.Grid.of(3, 2))
                 .build()
                )
      .create()
     );

  // 对应格式一定的表格,直接采用字符串替换即可
  put("tab4", new HashMap<String, Object>() {{
    put("contractName", "第一季度财务报告");
    put("contractDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
    put("company", "xxx有限责任公司");
    put("money", 10089.33);
  }});
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);

文档效果:在这里插入图片描述

引入标签

插入图片

上面也有插入图片的方式,但是通过引入标签的方式插入图片时,可以先在 word 模板文件中提前编辑好图片的样式,通过替换图片的方式,会保留原本设置好的样式。

在 docx 模板文件中先插入一张图片,并且调整好图片的样式,之后右键图片选择【查看可选文字】,在可选文字中通过 {{xxx}} 的方式填写属性名称。

【特别提醒】貌似 WPS 没有可选文字的功能,不确定是不是 WPS 版本的原因,反正我没找到可选文字。

因此我特地把 WPS 卸载之后换成了 Office 工具。

在这里插入图片描述

案例代码:

// 模板文件
String templateFilePath = "/word_template/quote_demo01.docx";
// 输出文件
String outputFilePath = "D:/output.docx";
// 插入文本数据
Map<String, Object> templateData = new HashMap<String, Object>() {{
  // 直接插入本地图片,这里会保留模板文件的图片样式
  put("label1", Pictures.ofLocal("C:/Users/17279/Pictures/head.jpg").create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);

文档效果:

在这里插入图片描述

插入单系列图表

单系列图表指的是饼图(3D饼图)、圆环图等。

同引入标签插入图片一样,在插入图表的时候,需要在 docx 模板中创建一个单系列的图表,设置好样式,之后右键图表选择【查看可选文字】,在可选文字中通过 {{xxx}} 的方式填写属性名称。

在这里插入图片描述

案例代码:

// 模板文件
String templateFilePath = "/word_template/quote_demo02.docx";
// 输出文件
String outputFilePath = "D:/output.docx";
// 插入文本数据
Map<String, Object> templateData = new HashMap<String, Object>() {{
  // 添加单系列图表的表格数据
  put("label2", Charts
      .ofSingleSeries("商品类型", new String[]{"电器类", "数码类", "生活用品类", "食品类", "其他"})
      .series("数量", new Integer[]{30, 8, 25, 11, 3})
      .create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);

文档效果:

在这里插入图片描述

插入多系列图表

多系列图表指的是条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、散点图等。

模板文件如下:

在这里插入图片描述

案例代码:

// 模板文件
String templateFilePath = "/word_template/quote_demo03.docx";
// 输出文件
String outputFilePath = "D:/output.docx";
// 插入文本数据
Map<String, Object> templateData = new HashMap<String, Object>() {{
  // 添加单系列图表的表格数据
  put("label3", Charts
      .ofMultiSeries("销售额", new String[]{"第一季度", "第二季度", "第三季度", "第四季度"})
      .addSeries("电器类", new Integer[]{22, 25, 28, 25})
      .addSeries("数码类", new Integer[]{5, 10, 8, 4})
      .addSeries("其他", new Integer[]{30, 42, 22, 33})
      .create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);

文档效果:在这里插入图片描述

插入组合图表

组合图表指的是由多系列图表(柱形图、折线图、面积图)组合而成的图表。

模板文件如下:

在这里插入图片描述

案例代码:

// 模板文件
String templateFilePath = "/word_template/quote_demo04.docx";
// 输出文件
String outputFilePath = "D:/output.docx";
// 插入文本数据
Map<String, Object> templateData = new HashMap<String, Object>() {{
  // 添加单系列图表的表格数据
  put("label4", Charts
      .ofComboSeries("汽车销售额", new String[]{"第一季度", "第二季度", "第三季度", "第四季度"})
      // 添加柱状图数据
      .addBarSeries("比亚迪", new Double[]{12.3, 11.5, 9.7, 12.0})
      .addBarSeries("广汽", new Double[]{6.2, 5.8, 5.7, 6.6})
      .addBarSeries("小米", new Double[]{0.0, 0.0, 10.2, 11.2})
      // 添加折线图数据
      .addLineSeries("国内均值", new Double[]{10.0, 12.2, 11.2, 9.8})
      .addLineSeries("全球均值", new Double[]{8.3, 10.2, 10.0, 8.8})
      .create());
}};
// 文件生成
PoitlUtils.generateWordFile(templateData, templateFilePath, outputFilePath);

文档效果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

英国牛津大学博士后职位—统计学

牛津大学&#xff08;University of Oxford&#xff09;&#xff0c;简称“牛津”&#xff08;Oxford&#xff09;&#xff0c;位于英国牛津&#xff0c;是一所公立研究型大学&#xff0c;采用传统学院制。是罗素大学集团成员&#xff0c;被誉为“金三角名校”、“G5超级精英大…

python 第6册 辅助excel 002 批量创建非空白的 Excel 文件

---用教授的方式学习 此案例主要通过使用 while 循环以及 openpyxl. load_workbook()方法和 Workbook 的 save()方法&#xff0c;从而实现在当前目录中根据已经存在的Excel 文件批量创建多个非空白的Excel 文件。当运行此案例的Python 代码&#xff08;A002.py 文件&#xff0…

论文阅读_优化RAG系统的检索

英文名称: The Power of Noise: Redefining Retrieval for RAG Systems 中文名称: 噪声的力量&#xff1a;重新定义RAG系统的检索 链接: https://arxiv.org/pdf/2401.14887.pdf 作者: Florin Cuconasu, Giovanni Trappolini, Federico Siciliano, Simone Filice, Cesare Campag…

MyBatis Plus条件构造器使用

1Wrapper&#xff1a; 条件构造抽象类&#xff0c;最顶端父类 1.1 AbstractWrapper&#xff1a; 用于查询条件封装&#xff0c;生成 sql 的 where 条件 1.2 QueryWrapper&#xff1a; Entity 对象封装操作类&#xff0c;不是用lambda语法 1.3 UpdateWrapper&#xff1a; Update…

[Go 微服务] go-micro + consul 的使用

文章目录 1.go-micro 介绍2.go-micro 的主要功能3.go-micro 安装4.go-micro 的使用4.1 创建服务端4.2 配置服务端 consul4.3 生成客户端 5.goodsinfo 服务5.1 服务端开发5.2 客户端开发 1.go-micro 介绍 Go Micro是一个简化分布式开发 的微服务生态系统&#xff0c;该系统为开…

java热部署idea插件「jrebel安装教程」

告别漫长的项目重启等待&#xff0c;让开发像写诗一样流畅~ jrebel安装包下载 jrebel版本需要下比较老的版本&#xff0c;我用的是22.4.1的版本&#xff08;如果不差钱&#xff0c;可以支持一下正版&#xff0c;直接选择最新的版本即可&#xff09; 下载地址&#xff1a;传送门…

Python逻辑控制语句 之 判断语句--if else结构

1.if else 的介绍 if else &#xff1a;如果 ... 否则 .... 2.if else 的语法 if 判断条件: 判断条件成立&#xff0c;执行的代码 else: 判断条件不成立&#xff0c;执行的代码 &#xff08;1&#xff09;else 是关键字, 后⾯需要 冒号 &#xff08;2&#xff09;存在冒号…

链表-求链表中环的入口结点(easy)

目录 一、问题描述 二、解题思路 三、代码实现 四、刷题链接 一、问题描述 二、解题思路 本题基本思路&#xff1a; 1.设置一个hashSet来存储已经访问过的链表结点地址&#xff0c;注意不要直接存储链表内元素&#xff0c;因为链表内元素可能存在重复的&#xff0c;地址是不…

uniapp uniCloud云开发

uniCloud概述 uniCloud 是 DCloud 联合阿里云、腾讯云、支付宝云&#xff0c;为开发者提供的基于 serverless 模式和 js 编程的云开发平台。 uniCloud 的 web控制台地址&#xff1a;https://unicloud.dcloud.net.cn 文档&#xff1a;https://doc.dcloud.net.cn/uniCloud/ un…

【高考志愿】集成电路科学与工程

目录 一、专业概述 二、课程设置 三、就业前景 四、适合人群 五、院校推荐 六、集成电路科学与工程专业排名 一、专业概述 集成电路科学与工程&#xff0c;这一新兴且引人注目的交叉学科&#xff0c;正在逐渐崭露头角。它集合了电子工程、计算机科学、材料科学等多个领域的…

Kotlin中对空的很多处理

代码图片直观效果 逐行解释Kotlin中对空的各种情况的使用 private fun testNull() {val flag 1var name: String? nullvar user: User? // 有警告, 因为下面的赋值可以和这一行定义合并var zhangUser: User? User()var wangUser: User User() // 提示Explicitly given t…

Unity 字体创建时候容易导致字体文件不正确的一种情况

上面得到了两种字体格式&#xff0c;一种是TextMeshPro的&#xff0c;另一种是Unity UI系统中默认使用的字体资源。其原因是创建的位置不同导致的。 1.下面是TextMeshPro字体创建的位置 2&#xff1a;下面是Unity UI系统中默认使用的字体资源

Java学习【IO流:深入理解与应用(上)】

Java学习【IO流&#xff1a;深入理解与应用&#xff08;上&#xff09;】 &#x1f343;1.IO流体系结构&#x1f343;2.FileOutputStream&#x1f341;2.1FileOutputStream写数据的三种方式&#x1f341;2.2换行和续写 &#x1f343;3.FileInputStream&#x1f341;3.1每次读取…

pbootcms后台获取前端表单留言页面url

pbootcms在线留言表单&#xff0c;用户在网页前端提交表单成功后&#xff0c;在网站后台如何获取表单留言页面的url这个参数呢&#xff1f;下面举例说明&#xff1a;首先&#xff0c;我们在PBootcms后台对应的表单&#xff0c;添加需要记录的表单字段&#xff0c;例如 添加liuy…

微服务-网关Gateway

个人对于网关路由的理解&#xff1a; 网关就相当于是一个项目里面的保安&#xff0c;主要作用就是做一个限制项。&#xff08;zuul和gateway两个不同的网关&#xff09; 在路由中进行配置过滤器 过滤器工厂&#xff1a;对请求或响应进行加工 其中filters&#xff1a;过滤器配置…

停车场智能化管理:车位引导系统实现车位资源优化与数据分析

随着城市汽车保有量的不断增长&#xff0c;停车难问题日益凸显。尤其是在高峰时段&#xff0c;寻找停车位和取车成为了许多车主的头疼问题。为了解决这一难题&#xff0c;维小帮智能车位引导系统应运而生&#xff0c;它利用先进的技术手段&#xff0c;帮助车主快速找到停车位&a…

PySide(PyQt)在图像上画线

1、按鼠标左键任意画线 import sys from PySide6.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget from PySide6.QtGui import QPainter, QPixmap, QMouseEvent, QColor, QPen from PySide6.QtCore import Qt, QPointclass PaintLabel(QLabel):def __init__(self…

Linux自动化交互脚本expect开发

在日常开发任务中&#xff0c;运行shell脚本有时候会提示输入密码的操作&#xff0c;如何让脚本自动输入密码呢&#xff1f;这时使用expect帮我们输入&#xff0c;Expect是基于Tcl发展而来的&#xff0c;它不仅可以进行交互&#xff0c;还可以根据程序的提示模拟标准输入&#…

pytorch-01

加载mnist数据集 one-hot编码实现 import numpy as np import torch x_train np.load("../dataset/mnist/x_train.npy") # 从网站提前下载数据集&#xff0c;并解压缩 y_train_label np.load("../dataset/mnist/y_train_label.npy") x torch.tensor(y…

【JVM-01】引言

【JVM-01】引言 1. 什么是JVM&#xff1f;2. JDK、JRE、JVM比较3.常用的JVM有那些4.学习路线 1. 什么是JVM&#xff1f; JVM即 Java Virtual Machine(Java虚拟机)&#xff0c;是Java程序运行的环境(Java 二进制字节码运行环境)。 好处&#xff1a; 一次编写&#xff0c;到处…