目录

准备工作

文本的简单实现

图片的简单实现

表格的简单实现

表格的实现

表格循环的实现

列表的简单实现

统计图表的实现

多系列表的方式

单系列表的方式

组和图表的实现

页码的实现

目录的实现

poi-tl官方地址:

扩展(需要借助其他框架实现)

html写入到word中

水印的实现

目录的实现


这是一个国人开发的框架,感觉编码习惯更加复合国人吧,而且模板定义和使用起来确实挺方便的

准备工作

  • 我们需要引入poi-tl的jar包

            <dependency>
                <groupId>com.deepoove</groupId>
                <artifactId>poi-tl</artifactId>
                <version>1.10.0</version>
            </dependency>
    
  • 注意:还要引入对应版本的poi的jar包

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>
    

文本的简单实现

1.定义poi-tl的word模板

  • 在poi-tl中定义模板很简单,只需要使用{{xxxx}}作为占位符即可,然后存储word文件,放到项目中就可以直接使用

2.然后就可以直接定义代码实现根据当前模板生成word文件了

  •   @SpringBootTest
      public class PoiTlTest {
      
          @Test
          public void test() {
              try {
                  //获取模板文件地址(根据自己的文件位置定义)
                  String path = PoiTlTest.class.getResource("/word/test.docx").toURI().getPath();
                  //定义填充内容和对应关系
                  Map<String, Object> map = new HashMap<>();
                  map.put("title", "标题党");
                  map.put("body", "内容党");
                  XWPFTemplate template = XWPFTemplate.compile(path).render(map);
                  //生成新的模板(根据自己想要生成的文件位置定义)
                  template.writeAndClose(new FileOutputStream( "src/main/resources/word" + "/test2.docx"));
              } catch (Exception e) {
                  throw new RuntimeException(e.getMessage());
              }
      
          }
      }
    

3.运行,得到填充后的word

图片的简单实现

1.图片的填充,使用的是{{@xxx}}定义的,注意前面有个@,否则会是对象的地址值

2.代码实现

方式一:可以直接在value中定义图片的路径实现(只是简单的方式,不能进行复杂的操作)

String iamgeStream = PoiTlTest.class.getResource("/word/111.png").toURI().getPath();
map.put("image", iamgeStream);
XWPFTemplate template = XWPFTemplate.compile(path).render(map);

方式二:借助poi-tl提供的PictureRenderData的方式创建(可以进行复杂操作,比如大小,旋转,边框的控制)

String iamgeStream = PoiTlTest.class.getResource("/word/111.png").toURI().getPath();
//第一个为图片宽,第二个为高,第三个图片类型,第四个输入流
PictureRenderData pictureRenderData = new PictureRenderData(100, 100, iamgeStream);
//将图片也放入到map中
map.put("image", pictureRenderData);
XWPFTemplate template = XWPFTemplate.compile(path).render(map);

如果我们想用图片的原有大小,而不是手动可以使用下面的方式获取图片的又有大小,然后使用

// 获取图片的原始宽度和高度
BufferedImage read = ImageIO.read(new File(iamgeStream));
int width = read.getWidth();
int height = read.getHeight();

3.写入后

4.图片的替换

图片的引用标签(可以替换图片,且不会影响图片的样式和大小等)

首先要插入图片,然后定义可选文字

office定义

wps的方式我没找到怎么给图片设置可选文字

代码实现,需要借助Pictures类

String iamgeStream = PoiTlTest.class.getResource("/word/111.png").toURI().getPath();
map.put("imageStyle", Pictures.ofLocal(iamgeStream).create());

实现

表格的简单实现

表格的实现

1.直接通过{{#xxxxxx}}的方式定义一个占位符,这个就是代表这是一个表格(我们直接将手动绘制的表格替换这个占位符)

2.定义我们表格的绘制代码(这里要借助TableRenderData对象)

String[][] table = {
        new String[]{"姓名", "性别"},
        new String[]{"爱国", "16"},
        new String[]{"爱党", "35"}
};
TableRenderData tableRenderData = Tables.of(table).create();
map.put("table",tableRenderData);

3.结果

4.合并单元格

没有数据的用null表示,然后在TableRenderData中控制合并的位置

横着的

String[][] table = {
        new String[]{"姓名", "性别","地址"},
        new String[]{"爱国", "16","未来"},
        new String[]{"爱党", "35","富强"},
        new String[]{"爱家庭", null,null}
};
TableRenderData tableRenderData = Tables.of(table)
        .mergeRule(MergeCellRule
                .builder()
                //前面的参数指的从哪里开始,后面的指的结束(纵坐标,横坐标)
                .map(MergeCellRule.Grid.of(3, 0), MergeCellRule.Grid.of(3, 2))
                .build()
        )
        .create();
map.put("table",tableRenderData);

竖着的

只需要修改纵坐标和横坐标,和对应的数据为null即可

.map(MergeCellRule.Grid.of(1, 2), MergeCellRule.Grid.of(3, 2))

5.还有种表格的方式,我们的数据都来自一个对象,可以这样定义

代码实现

Student student = new Student("中国的未来", 25,"未来");
map.put("student", student);

实现

表格循环的实现

(下面的是行表格的实现,列表格是在第一个列中定义{{xxx}},其他是一致的)

用到了poi-tl的插件功能

首先定义表格,我们要在表格中定义我们表格的对象集合占位符{{xxx}},然后在表中定义对象的字段占位符[xxxx],两者都要有(这里好像是这样的)

首先定义一个实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
class Student{
    private String name;
    private Integer age;
    private String address;
}

创建填充的对象集合数据,且添加到map中

            //1.学生数据
            List<Student> students = new ArrayList<>();
            Student e = new Student("靓仔", 17, "中国台湾");
            Student e2 = new Student("帅哥", 18, "上海");
            students.add(e);
            students.add(e2);
            map.put("students", students);

定义我们需要进行表格的绑定的key

//创建行循环策略
LoopRowTableRenderPolicy rowTableRenderPolicy = new LoopRowTableRenderPolicy();
//告诉模板引擎,要在employees做行循环,绑定行循环策略
Configure configure = Configure.builder().bind("students", rowTableRenderPolicy).build();

将上面的configure作为参数放到tempalte中

//相对于文本和图片,多传入了一个configure参数
XWPFTemplate template = XWPFTemplate.compile(path,configure).render(map);

实现

列表的简单实现

首先定义我们列表的模板,使用{{*xxxxx}}的方式代表是个列表

实现也很好实现,借助Numbering对象,放入到map中即可

写法一:手动加入

map.put("list", Numberings.create("秦","叔","宝"));

写法二:传入集合(转为数组传入)

            List<String>  list = new ArrayList<>();
            list.add("13456");
            list.add("134567");
            list.add("1345678");
            //转化为数组
            String[] array = list.toArray(new String[list.size()]);
            map.put("list", Numberings.create(array));

实现

我们的列表结构还可以指定

列表类型

DECIMAL

//1. 2. 3.

DECIMAL_PARENTHESES

//1) 2) 3)

BULLET

//● ● ●

LOWER_LETTER

//a. b. c

LOWER_ROMAN

//i ⅱ ⅲ

UPPER_LETTER

//A. B. C.

代码实现

通过指定Numberings.of(NumberingFormat)指定类型,然后需要使用addItem进行添加

Numberings.NumberingBuilder numberingBuilder = Numberings.of(NumberingFormat.DECIMAL);
for (String s : array) {
     numberingBuilder.addItem(s);
}
NumberingRenderData numberingRenderData = numberingBuilder.create();
map.put("list", numberingRenderData);

实现

统计图表的实现

首先导入一个图表,然后需要设置图表的可选文字{{xxx}}格式(用的都是引用标签的方式)

office(我用到可选文字的地方都会用office的方式,下面有wps的设置可选文字步骤)

office版本不同,可能位置不同,也可以通过下面的方式查找

wps的方式

需要借助ChartMultiSeriesRenderData对象

多系列表的方式

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

ChartMultiSeriesRenderData chart = Charts
        .ofMultiSeries("图表的名称", new String[] { "一月", "二月" })//代表横坐标和图表名称
        //addSeries表示的是增加纵坐标,这里三个就是三个纵坐标,其中第二个参数是和上面的横坐标对应的,所以一定要数量对应
        .addSeries("蔬菜", new Double[] { 15.0, 6000.0 })
        .addSeries("水果", new Double[] { 223.0, 119.0 })
        .addSeries("百货",new Double[] { 33.0, 23.0 })
        .create();

ap.put("chart", chart);

实现

单系列表的方式

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

代码实现,需要借助ChartSingleSeriesRenderData对象(和多类型图表不一样)

ChartSingleSeriesRenderData pieChart = Charts
        .ofSingleSeries("图标的名称", new String[] { "一月", "二月","三月" })
        .series("销量", new Integer[] { 999, 666,66 })
        .create();

map.put("pieChart", pieChart);

实现:

组和图表的实现

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

代码实现,他需要借助ChartMultiSeriesRenderData对象

ChartMultiSeriesRenderData chartMultiSeriesRenderData = Charts
        .ofComboSeries("图表的名称", new String[]{"啦啦啦", "德玛西亚"})//横坐标和图名
        .addBarSeries("柱状图1", new Double[]{15.0, 6.0})//表示的柱状图
        .addBarSeries("柱状图2", new Double[]{60.0, 90.0})
        .addBarSeries("柱状图3", new Double[]{90.0, 110.0})
        .addLineSeries("折线图1", new Double[]{120.0, 290.0})//表示的折线图
        .addLineSeries("折线图2", new Double[]{300.0, 130.0})
        .create();

map.put("combChart", chartMultiSeriesRenderData);

实现

页码的实现

这个只需要在word中设置好页面,不需要我们操作,word会自动增加页码

目录的实现

目录借助poi-tl提供的new TOCRenderPolicy()只能实现office的,而且客户每次打开都要点击一下,不方便,

解决方法可以借助spire.doc框架,这个相对于来说生成目录比较方便,下面扩展目录下中有实现步骤

poi-tl官方地址:

还有很多功能,这里不在介绍,可以通过官方文档进行学习

http://deepoove.com/poi-tl[这里是图片026]http://deepoove.com/poi-tl

扩展(需要借助其他框架实现)

我们的poi-tl主要专注于文档模板处理,如动态替换文本、插入表格等,所以有些功能是无法实现的或支持不好,比如水印,html的写入,目录的实现,可以借助poi-tl扩展框架poi-tl-ext,也可以直接借助其他第三方框架

html写入到word中

我们需要使用一些在poi-tl上的扩展插件,可以引用poi-tl-ext插件

        <dependency>
            <groupId>io.github.draco1023</groupId>
            <artifactId>poi-tl-ext</artifactId>
            <version>0.4.2</version>
        </dependency>

HtmlRenderPolicy(还可以用来处理html的表格)

模板中还是使用{{xxxxx}}作为占位符(这里就省略了)

html字符串

String FIRE_EXTINGUISHER= new  String("<h2><span style="font-size: 20px; font-family: 宋体; ">一.测试一号</span></h2><p style="text-indent: 24pt;"><span style="font-family: 宋体;font-size: 16px;color: red">1)宋体且红色</span></p><p style="text-indent: 24pt;"><span style="font-family: 宋体;font-size: 16px;">2)宋体且黑色</span></p><p style="text-indent: 24pt;"><span style="font-family: 宋体;font-size: 16px;">3)宋体黑色</span></p></p><p style="text-indent: 24pt;"><span style="font-family: 宋体;font-size: 16px;color: blue;">4)宋体且蓝色</span></p>");

将html字符串放到到map中

map.put("htmlTest",htmlTest);

定义数据和插件绑定,且使用

Configure configure = Configure.builder().bind("htmlTest", new HtmlRenderPolicy()).build();
XWPFTemplate template = XWPFTemplate.compile(path, configure).render(map);

实现

poi-tl插件的使用,如果是多个的话,可以通过下面的方式定义

Configure config = Configure.builder().build();
config.customPolicy("xxx", new HtmlRenderPolicy());
config.customPolicy("xxx", new TOCRenderPolicy());
水印的实现

需要借助spire.doc框架(poi-tl实现不了添加水印)

        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.doc.free</artifactId>
            <version>5.2.0</version>
        </dependency>

代码实现(注意,如果使用的poi-tl生成的word,一定要等poi-tl生成文档后,对生成的新word进行加水印)

// 加载现有的Word文档
Document document = new Document();
document.loadFromFile("src/main/resources/word" + "/test2.docx");
TextWatermark txtWatermark = new TextWatermark();// 创建文本水印
txtWatermark.setText("这是一个大大的水印");//设置文本水印格式
txtWatermark.setFontName("仿宋");//字体
txtWatermark.setFontSize(28);//字号
txtWatermark.setColor(Color.red);//颜色
txtWatermark.setLayout(WatermarkLayout.Diagonal);//文字倾斜角度 此处使用斜对角
txtWatermark.setSemitransparent(true);//半透明
document.setWatermark(txtWatermark);// 将文本水印应用到文档
// 保存修改后的文档
document.saveToFile("src/main/resources/word" + "/test2.docx", FileFormat.Docx);

效果图

水印图片的实现

Document document = new Document();
document.loadFromFile("src/main/resources/word" + "/test2.docx", FileFormat.Docx);

PictureWatermark picture = new PictureWatermark();
String iamgeStream2 = PoiTlTest.class.getResource("/word/111.png").toURI().getPath();
picture.setPicture(iamgeStream2);
picture.setScaling(150);
picture.isWashout(false);
document.setWatermark(picture);

document.saveToFile("src/main/resources/word" + "/test2.docx", FileFormat.Docx);

效果

目录的实现

也是借助spire.docx框架

我们要在word模板中插入一个目录用来表示目录的位置,然后我们要将作为目录的内容设置称标题,只有被设置成标题才会被识别且生成目录

代码实现(会自动生成)

Document dd = new Document();
dd.loadFromFile("src/main/resources/word" + "/test2.docx", FileFormat.Docx);
dd.updateTableOfContents();
dd.saveToFile("src/main/resources/word" + "/test2.docx");

效果

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐