poi-tl的使用(通俗易懂,全面,内含动态表格实现 包会!!)

最近在做项目时候有一个关于解析Html文件,然后将解析的数据转化成word的需求,经过调研,使用poi-tl来实现这个需求,自己学习花费了一些时间,现在将这期间的经验总结起来,让大家可以快速入门

poi-tl的介绍

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

官网地址:中文文档地址

源码地址:https://github.com/Sayi/poi-tl

poi-tl的快速入门

  • 引入依赖
<!--poi-tl-->
<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.0</version>
</dependency>

文本标签(常用)

用法:{{var}}

支持的数据类型:

  • String :文本

  • TextRenderData :有样式的文本

  • HyperlinkTextRenderData :超链接和锚点文本

  • Object :调用 toString() 方法转化为文本

推荐使用工厂 Texts 构建文本模型。

   //文本标签@Testpublic void textTest() throws IOException {//解析模板XWPFTemplate template = XWPFTemplate.compile("D://hjl//textTemplate.docx");//封装模型数据HashMap<String, Object> map = new HashMap<>();map.put("text1","我是普通文本");map.put("text2",Texts.of("我是带有样式的文本").color("000000").bold().create());map.put("text3",Texts.of("我是用来处理超链接").link("http://www.baidu.com").create());map.put("text4",Texts.of("我是用来处理锚点文本").anchor("anchor11").create());//渲染数据template.render(map);//以文件形式输出template.writeAndClose(new FileOutputStream("D://hjl//textTemplate1.docx"));}

模板:

 

生成的结果:

图像标签(常用)

用法:图片标签以@开始:{{@var}}

数据模型:

  • String :图片url或者本地路径,默认使用图片自身尺寸

  • ByteArrayPictureRenderData

  • FilePictureRenderData

  • UrlPictureRenderData

推荐使用工厂 Pictures 构建图片模型。

@Test
public void imageTest() throws IOException {//解析模板XWPFTemplate template = XWPFTemplate.compile("D://hjl//imageTemplate.docx");//封装模型数据HashMap<String, Object> map = new HashMap<>();//处理本地图片,大小默认为图大小(以url路径的形式插入)map.put("image1","C:\\Users\\admin\\Desktop\\工作日志\\微信图片_20240407110311.jpg");map.put("svg", "https://img.shields.io/badge/jdk-1.6%2B-orange.svg");// 设置文件图片大小map.put("image2", Pictures.ofLocal("C:\\Users\\admin\\Desktop\\工作日志\\微信图片_20240407110311.jpg").size(120, 120).create());// 图片流(以流的方式插入)map.put("streamImg", Pictures.ofStream(new FileInputStream("C:\\Users\\admin\\Desktop\\工作日志\\微信图片_20240407110311.jpg"), PictureType.JPEG).size(100, 120).create());// 网络图片(注意网络耗时对系统可能的性能影响,根据URL链接加载图片,并根据给定的尺寸进行大小调整,以对象的形式插入)map.put("urlImg", Pictures.ofUrl("http://deepoove.com/images/icecream.png").size(100, 100).create());// 将生成一个bufferImage,以缓冲图像的的形式写入到模板中int width = 200;int height = 200;// 创建一个BufferedImage实例BufferedImage bufferImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取Graphics2D对象,并在图像上绘制内容Graphics2D g2d = bufferImage.createGraphics();g2d.setColor(Color.RED); // 设置颜色为红色int[] xPoints = {width/2, 0, width}; // 三角形的x坐标int[] yPoints = {0, height, height}; // 三角形的y坐标g2d.fillPolygon(xPoints, yPoints, 3); // 绘制填充的三角形g2d.dispose();// java图片,我们可以利用Java生成图表插入到word文档中map.put("buffered", Pictures.ofBufferedImage(bufferImage, PictureType.PNG).size(100, 100).create());//渲染数据template.render(map);//以文件形式输出template.writeAndClose(new FileOutputStream("D://hjl//imageTemplate1.docx"));
}

模板:

渲染后的word:

 

表格标签(常用)

用法:表格标签以#开始:{{#var}}

数据模型:

  • TableRenderData

推荐使用工厂 Tables 、 Rows 和 Cells 构建表格模型。

@Test
public void tableTest() throws IOException {//解析模板XWPFTemplate template = XWPFTemplate.compile("D://hjl//tableTemplate.docx");//封装模型数据HashMap<String, Object> map = new HashMap<>();//1  一个2行2列的表格map.put("table0", Tables.of(new String[][] {new String[] { "00", "01" },new String[] { "10", "11" }}).border(BorderStyle.DEFAULT).create());//2  第0行居中且背景为蓝色的表格RowRenderData row0 = Rows.of("姓名", "学历").textColor("FFFFFF").bgColor("4472C4").center().create();//第一行默认形式ArrayList<String> strings = new ArrayList<>();strings.add("李四");strings.add("博士");RowRenderData row1 = Rows.create("李四", "博士");map.put("table1", Tables.create(row0, row1));//3  合并第1行所有单元格的表格RowRenderData row00 = Rows.of("列0", "列1", "列2").center().bgColor("4472C4").create();RowRenderData row11 = Rows.create("没有数据", null, null);//规定合并单元格规则MergeCellRule rule = MergeCellRule.builder().map(MergeCellRule.Grid.of(1, 0), MergeCellRule.Grid.of(1, 2)).build();map.put("table2", Tables.of(row00, row11).mergeRule(rule).create());//渲染数据template.render(map);//以文件形式输出template.writeAndClose(new FileOutputStream("D://hjl//tableTemplate1.docx"));
}

 模板:

渲染结果:

 

 列表

用法:列表标签以*开始:{{*var}}

数据模型:

  • List<String>

  • NumberingRenderData

推荐使用工厂 Numberings 构建列表模型。

 

 

@Test
public void listTest() throws IOException {//解析模板XWPFTemplate template = XWPFTemplate.compile("D://hjl//listTemplate.docx");//封装模型数据HashMap<String, Object> map = new HashMap<>();ArrayList<String> strings = new ArrayList<>();strings.add("text1");strings.add("text2");strings.add("text3");map.put("list1",strings);//列表样式//DECIMAL //1. 2. 3.//DECIMAL_PARENTHESES //1) 2) 3)//BULLET //● ● ●//LOWER_LETTER //a. b. c.//LOWER_ROMAN //i ⅱ ⅲ//UPPER_LETTER //A. B. C.map.put("list2", Numberings.of(NumberingFormat.DECIMAL).addItem("text1").addItem("text2").create());//渲染数据template.render(map);//以文件形式输出template.writeAndClose(new FileOutputStream("D://hjl//listTemplate1.docx"));
}

模板:

 

结果:

这是word识别有点问题 

 

区块对

用法:区块对由前后两个标签组成,

开始标签以?标识,结束标签以/标识:{{?sections}}{{/sections}}

  • 区块对在处理一系列文档元素的时候非常有用,位于区块对中的文档元素可以被渲染零次,一次或N次,这取决于区块对的取值。
  • False或空集合

        隐藏区块中的所有文档元素

  • 非False且不是集合

        显示区块中的文档元素,渲染一次

  • 非空集合

        根据集合的大小,循环渲染区块中的文档元素

简单总结:对于False或空集合,就是不会显示区块对中的数据;对于非False且不是集合,只渲染一次区块对中的模板;对于集合,会根据集合大小,多次渲染

@Test
public void sectionTest() throws IOException {//解析模板XWPFTemplate template = XWPFTemplate.compile("D://hjl//sectionTemplate.docx");//封装模型数据HashMap<String, Object> map = new HashMap<>();//当数据为false,null,集合大小为0时,区块对的内容不展示map.put("section1",false);map.put("section2",null);map.put("section3",new ArrayList());map.put("section4",true);String name = "jack";map.put("section5",name);ArrayList<String> strings = new ArrayList<>();strings.add("a");strings.add("b");strings.add("c");strings.add("d");HashMap<String, Object> stringObjectHashMap = new HashMap<>();stringObjectHashMap.put("value",strings);map.put("section6",stringObjectHashMap);//渲染数据template.render(map);//以文件形式输出template.writeAndClose(new FileOutputStream("D://hjl//sectionTemplate1.docx"));
}

模板:

渲染结果

 

嵌套

用法:嵌套又称为导入、包含或者合并,以+标识:{{+var}}

数据模型:

  • DocxRenderData

推荐使用工厂 Includes 构建嵌套模型。

实现:

@Test
public void includeTest() throws IOException {//解析模板XWPFTemplate template = XWPFTemplate.compile("D://hjl//includeTemplate.docx");//封装模型数据HashMap<String, Object> map = new HashMap<>();map.put("mainContent","我是主模板的数据1111");//子模版数据HashMap<String, Object> subMap = new HashMap<>();subMap.put("name","jack");subMap.put("age","18");map.put("nested", Includes.ofLocal("D://hjl//sub.docx").setRenderModel(subMap).create());//渲染数据template.render(map);//以文件形式输出template.writeAndClose(new FileOutputStream("D://hjl//includeTemplate1.docx"));
}

 

主 模板:

子模版:

结果:

复杂图表

用法:需要事先在模板中加入图标的结构,然后修改可选问题,这样就会替换数据

//使用工厂 Charts 构建图表模型
@Test
public void ChartsTest() throws IOException {//图表渲染出来后,后面具体的样式可以在图标中调整//解析模板XWPFTemplate template = XWPFTemplate.compile("D://hjl//ChartsTemplate.docx");//封装模型数据HashMap<String, Object> map = new HashMap<>();//引用图片// 设置文件图片大小map.put("image", Pictures.ofLocal("C:\\Users\\admin\\Desktop\\工作日志\\微信图片_20240407110311.jpg").size(120, 120).create());//多系列图表条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、散点图等//柱形图ChartMultiSeriesRenderData chart = Charts.ofMultiSeries("医院综合排名", new String[] { "齐鲁医院","泰山医院","第二人民医院","第三医院"}).addSeries("数据质量排名", new Double[] { 70.5,40.6,22.7,85.4}).addSeries("价格质量排名", new Double[] { 80.5,75.6,72.7,85.4}).create();map.put("barChart", chart);//折线图ChartMultiSeriesRenderData qst = Charts.ofMultiSeries("任务趋势", new String[] { "06-10","06-11","06-12","06-13","06-14","06-15"}).addSeries("微信端", new Double[] { 70.5,40.6,22.7,85.4,700.0,40.8}).addSeries("PC端", new Double[] { 80.5,50.6,62.7,45.4,200.0,140.8}).addSeries("小程序端", new Double[] { 120.5,520.6,362.7,405.4,300.0,340.8}).create();map.put("qst", qst);//单系列图表指的是饼图(3D饼图)、圆环图等//饼图ChartSingleSeriesRenderData pie = Charts.ofSingleSeries("国家GDP对比", new String[] { "美国", "中国","日本","韩国" }).series("经济占比", new Integer[] { 50, 35,10,5 }).create();map.put("pieChart", pie);//组合图表指的是由多系列图表(柱形图、折线图、面积图)组合而成的图表。ChartMultiSeriesRenderData comb = Charts.ofComboSeries("MyChart", new String[] { "中文", "English" }).addBarSeries("countries", new Double[] { 15.0, 6.0 }).addBarSeries("speakers", new Double[] { 223.0, 119.0 }).addLineSeries("youngs", new Double[] { 323.0, 89.0 }).addLineSeries("NewLine", new Double[] { 123.0, 59.0 }).create();map.put("combChart", comb);//柱状图、折线图共存ChartMultiSeriesRenderData hntb = Charts.ofComboSeries("某省社会排名", new String[] { "城市1","城市2","城市3","城市4","城市5","城市6"}).addBarSeries("GDP",new Double[] {70.5,40.6,22.7,85.4,700.0,40.8}).addBarSeries("人口",new Double[] {80.5,50.6,62.7,45.4,200.0,140.8}).addLineSeries("指数",new Double[] {0.6,0.3,0.7,0.4,0.1,0.8}).create();map.put("hntb", hntb);//渲染数据template.render(map);//以文件形式输出template.writeAndClose(new FileOutputStream("D://hjl//ChartsTemplate1.docx"));}

模板:

结果:

 

到这里,poi-tl基本的用法都差不多介绍完了,还有一些没将的可以看官网的文档,里面有更多的细节

 

动态表格的实现

第一步:写一个类去继承    DynamicTableRenderPolicy  这个类,重写里面的render方法

render()的主要步骤:

  • 获取数据
  • 插入表格
  • 合并表格
public class DynamicTableProxy extends DynamicTableRenderPolicy {//渲染策略制定@Overridepublic void render(XWPFTable xwpfTable, Object tableData) throws Exception {//判断数据是否存在if (null == tableData) {return;}// 类型转化ServerTableData serverTableData = (ServerTableData) tableData;List<RowRenderData> serverDataList = serverTableData.getServerDataList();if(serverDataList.size()>0){// 1 先删除一行, demo中第一行是为了调整 三线表 样式(也是一个空行)xwpfTable.removeRow(1);//2 向表格中渲染数据// 行从中间插入, 因此采用倒序渲染数据for (int i = serverDataList.size() - 1; i >= 0; i--) {XWPFTableRow newRow = xwpfTable.insertNewTableRow(1);newRow.setHeight(400);for (int j = 0; j < 4; j++) {newRow.createCell();}// 渲染一行数据TableRenderPolicy.Helper.renderRow(newRow, serverDataList.get(i));}//3 合并表格TableTools.mergeCellsVertically(xwpfTable, 0, 1, 2);TableTools.mergeCellsVertically(xwpfTable, 0, 3, 4);}}}

第二步:封装数据

private ServerTableData getServerTableData() {ServerTableData serverTableData = new ServerTableData();List<RowRenderData> serverDataList = new ArrayList<>();for (int j = 0; j < 4; j++) {String value;RowRenderData serverData;//前二行if (j > 1) {value = "索隆";serverData = Rows.of(value, "喝酒", "三千世界", "无").center().create();}else {value = "路飞";serverData = Rows.of(value, "大鸡腿", "巨人手枪", "橡胶果实").center().create();}serverDataList.add(serverData);}List<Map<String, Object>> groupDataList = new ArrayList<>();Map<String, Object> groupData1 = new HashMap<>();groupData1.put("typeName", "索隆");groupData1.put("listSize", "2");Map<String, Object> groupData2 = new HashMap<>();groupData2.put("typeName", "路飞");groupData2.put("listSize", "2");groupDataList.add(groupData1);groupDataList.add(groupData2);serverTableData.setServerDataList(serverDataList);serverTableData.setGroupDataList(groupDataList);serverTableData.setMergeColumn(0);return serverTableData;
}

 

第三步:绑定策略

注意:这里绑定的oneTable是写在表格中的

@Test
void contextLoads() throws IOException {// 获取模板文件流InputStream resourceAsStream = new FileInputStream("D://template.docx");//poi-tl 配置ConfigureBuilder builder = Configure.builder();builder.useSpringEL(false);Map<String,Object> map = new HashMap<>();// 伪造一个表格数据//(生成表格数据)ServerTableData oneTable = getServerTableData();//单个表格map.put("oneTable",oneTable);builder.bind("oneTable",new DynamicTableProxy());//输出文件XWPFTemplate template = XWPFTemplate.compile(Objects.requireNonNull(resourceAsStream), builder.build()).render(map);template.writeAndClose(new FileOutputStream("D://out.docx"));}

 

 

@Data
public class ServerTableData {/***  携带表格中真实数据*/private List<RowRenderData> serverDataList;/*** 携带要分组的信息*/private List<Map<String, Object>> groupDataList;/*** 需要合并的列,从0开始*/private Integer mergeColumn;}

 

 模板:

结果

 

 

综合案例:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据产品有哪些分类?各类里知名大数据产品都有哪些?

随着互联网技术的持续进步和全球数字化转型的推进&#xff0c;我们正处于一个数据爆炸的时代。在这样的大背景下&#xff0c;大数据已经逐渐崭露头角&#xff0c;成为了推动各行各业发展的关键因素和核心资源。大数据不仅仅是指数据的规模巨大&#xff0c;更重要的是它蕴含的价…

Python八股文:基础知识Part2

1. Python中变量的保存和访问 Python中的变量实际上是一个指向对象的引用&#xff0c;每个对象都有一个唯一的标识符&#xff08;即内存地址&#xff09;。对于一些不可变对象&#xff0c;如字符串和整数&#xff0c;因为它们的值不可更改&#xff0c;所以当多个变量引用相同的…

彩虹聚合DNS管理系统源码

聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。本系统支持多用户&#xff0c;每个用户可分配不同的域名解析权限&#xff1b;支持API接口&#xff0c;支持获取域名…

建造者模式:构造复杂对象的艺术

在面向对象的设计中&#xff0c;建造者模式是一种重要的创建型设计模式&#xff0c;专门用来构建复杂的对象。它主要目的是将对象的构造代码与其表示代码分离&#xff0c;使同样的构建过程可以创建不同的表示。本文将详细介绍建造者模式的定义、实现、应用场景以及优缺点&#…

虚拟货币:数字金融时代的新工具

在数字化时代的到来之后&#xff0c;虚拟货币逐渐成为了一种广为人知的金融工具。虚拟货币是一种数字化的资产&#xff0c;它不像传统货币那样由政府或中央银行发行和监管。相反&#xff0c;虚拟货币通过密码学技术和分布式账本技术来实现去中心化的发行和交易。 虚拟货币的代…

内网通如何去除广告,内网通免广告生成器

公司使用内网通内部传输确实方便&#xff01;但是会有广告弹窗推送&#xff01;这个很烦恼&#xff01;那么如何去除广告呢&#xff01; 下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1CVVdWexliF3tBaFgN1W9aw?pwdhk7m 提取码&#xff1a;hk7m ID&#xff1a;…

如何进行宏观经济预测

理性预期经济学提出了理性预期的概念&#xff0c;强调政府在制定各种宏观经济政策时&#xff0c;要考虑到各行为主体预期对政策实施有效性的影响&#xff0c;积极促成公众理性预期的形成&#xff0c;从而更好地实现宏观调控的目标。政府统计要深入开展统计分析预测研究&#xf…

享元模式:优化资源利用的高效策略

在面向对象的软件开发中&#xff0c;享元模式是一种结构型设计模式&#xff0c;旨在减少内存使用&#xff0c;通过共享尽可能多的相似对象来提高应用程序的效率。本文将详细介绍享元模式的定义、实现、应用场景以及优缺点。 1. 享元模式的定义 享元模式&#xff08;Flyweigh…

免费的 ChatGPT 网站(六个)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、insCode二、讯飞星火三、豆包四、文心一言五、通义千问六、360智脑 现在智能…

PoE 技术

1 PoE 技术产生背景 随着 WLAN 、 VoIP 、网络视频监控等新业务的飞速发展,大量的无线 LAN 访问点、 IP 电话、 IP 网络摄像头等基于 IP 的终端出现在工业现场。这些设备通常数量众多、位置特殊 、 布线复杂、设备取电困难,其实施部署不仅消耗大量人力物力,…

终端界面外观修改

终端界面外观修改 考虑到实验报告等内容截取命令行会出现不清晰现象 所以特意对cmd命令行的界面外观修改方便打印的时候清晰显示内容 流程 1.右键命令行窗口&#xff0c;点击属性 2.点击颜色 3.选择屏幕背景&#xff0c;窗口颜色选择白色 4.选择屏幕文字&#xff0c;点…

【计算机毕业设计】基于Java+SSM的实战开发项目150套(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f9e1;今天给大家分享150的Java毕业设计&#xff0c;基于ssm框架&#xff0c;这些项目都经过精心挑选&#xff0c;涵盖了不同的实战主题和用例&#xff0c;可做毕业设计和课程…

SpringCloudAlibaba-整合nacos(二)

目录地址&#xff1a; SpringCloudAlibaba整合-CSDN博客 一、nacos服务部分 1.下载nacos&#xff0c;并执行数据库脚本&#xff1a;nacos-mysql.sql 2.修改配置文件&#xff0c;配置mysql 3.启动nacos ./startup.sh -m standalone 4.访问&#xff1a;http://127.0.0.1:884…

pytest常用钩子函数

1、什么叫钩子函数 在Pytest框架中&#xff0c;钩子函数是一种允许用户扩展或者自定义测试执行过程的机制。钩子函数允许用户在测试的不同阶段插入自定义的代码&#xff0c;以实现特定的行为&#xff0c;操作或处理。这种插入式的机制使得Pytest具有高度的灵活性和扩展性。 如…

苹果全力升级:用专注AI的M4芯片彻底改造Mac系列

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

964: 数细胞

样例&#xff1a; 解法&#xff1a; 1.遍历矩阵 2.判断矩阵[i][j]&#xff0c;若是未标记细胞则遍历相邻所有未标记细胞并标记&#xff0c;且计数 实现&#xff1a;遍历相邻所有未标记细胞 以DFS实现&#xff1a; function dfs(当前状态) {if (终止条件) {}vis[标记当前状…

基于深度学习的生活垃圾智能分类系统(微信小程序+YOLOv5+训练数据集+开题报告+中期检查+论文)

摘要 本文基于Python技术&#xff0c;搭建了YOLOv5s深度学习模型&#xff0c;并基于该模型研发了微信小程序的垃圾分类应用系统。本项目的主要工作如下&#xff1a; &#xff08;1&#xff09;调研了移动端垃圾分类应用软件动态&#xff0c;并分析其优劣势&#xff1b;分析了深…

深入解析实时数仓Doris:介绍、架构剖析、应用场景与数据划分细节

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! Doris是一款高性能、开源的实时分析数据仓库&#xff0c;旨在为用户提供毫秒级查询响应、高并发、高可用以及易于扩展的OLAP解决方…

【Qt 学习笔记】QWidget的geometry属性及window frame的影响

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ QWidget的geometry属性 文章编号&#xff1a;Qt 学习笔记 / 16 文章目…

VirusTaxo:病毒物种注释

https://github.com/omics-lab/VirusTaxo 安装 git clone https://github.com/omics-lab/VirusTaxo mamba create -n VirusTaxo python3.10 mamba activate VirusTaxo cd VirusTaxo python3 -m venv environment source ./environment/bin/activate pip install -r require…