poi

您所在的位置:网站首页 合并表格内容不变 poi

poi

2024-06-03 14:38:46| 来源: 网络整理| 查看: 265

一、在有些业务场景下,我们需要导出一些word文档的报告等,这里我推荐一下poi-tl,这是我开发当中用到的。由于业务数据的复杂性,easyWord没法满足需求,所以这里推荐使用poi-tl,因为它提供了针对处理复杂数据的很多接口策略,还可以根据自己具体的业务需求来扩展。

二、这次是关于如何动态合并单元格。参考了其他帖子,但是他们用到的数据都是固定的,但是对于动态数据是不适用的,下面直接上代码,分享一下我是如何处理的?

package com.cantai.qmsat.utils.poi; import com.cantai.qmsat.at.operate.entity.InstrumentEntity; import com.deepoove.poi.data.CellRenderData; import com.deepoove.poi.data.RowRenderData; import com.deepoove.poi.policy.DynamicTableRenderPolicy; import com.deepoove.poi.policy.TableRenderPolicy; import com.deepoove.poi.util.TableTools; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; /** * @author shijin * @create 2022-11-04 19:30 */ public class RowspanPolicy extends DynamicTableRenderPolicy { @Override public void render(XWPFTable table, Object data) throws Exception { int num = 0; if (null == data) return; List detailData = (List) data; if (null != detailData) { table.removeRow(2); // 循环插入行,必须采用这种遍历,不然数据会反过来 for (int i = detailData.size() - 1; i >= 0; i--) { //根据数据长度创建对应行数 XWPFTableRow insertNewTableRow = table.insertNewTableRow(2); for (int j = 0; j < 5; j++) { //根据列的数量创建对应单元格 insertNewTableRow.createCell(); } // 单行渲染 TableRenderPolicy.Helper.renderRow(table.getRow(2), detailData.get(i)); } //遍历完整个图表之后再合并 List list = new ArrayList(); HashMap nameNumMap = new HashMap(); for (int i = 0; i < detailData.size(); i++) { String typeName = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString(); list.add(typeName); } List collect = list.stream().distinct().collect(Collectors.toList()); for (String s : collect) { for (int i = 0; i < detailData.size(); i++) { String typeName1 = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString(); if (s == typeName1) { num++; } } nameNumMap.put(s, num); num = 0; } //开始合并 for (String s : collect) { //从我们map中取出刚才放入的单位的个数 Integer change = Integer.parseInt(String.valueOf(nameNumMap.get(s))); //开始循环数据 //元素第一次出现的位置 int firstLocation = list.lastIndexOf(s) + 1; int fromRow = firstLocation - change + 2; int toRow = list.lastIndexOf(s) + 2; if (change > 1) { TableTools.mergeCellsVertically(table, 1, fromRow, toRow); } } } } }

创建一个类RowspanPolicy继承DynamicTableRenderPolicy,重写render方法

准备数据:参考了官网的合并方法,data中的数据类型要转为RowRenderData,所以在组装数据的时候,直接组装成RowRenderData类型的,如下:

for (AfTtiInstrumentVo afTtiInstrumentVo : instrumentVos) { int i = instrumentVos.indexOf(afTtiInstrumentVo) + 1; DateFormat cst = new SimpleDateFormat("yyyy-MM-dd"); DateFormat gmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH); Date date1 = gmt.parse(afTtiInstrumentVo.getNextCalibrationDate().toString()); String date2 = cst.format(date1); RowRenderData rowRenderData = Rows.of(Integer.toString(i), afTtiInstrumentVo.getTestName(), afTtiInstrumentVo.getDeviceName(), afTtiInstrumentVo.getFactoryNumber(), date2).center().create(); instrumentList1.add(rowRenderData); }

数据准备好之后,开始重写DynamicTableRenderPolicy策略接口,首先是将数据逐个添加到每一个的单元格,如下:

//如果顺序遍历的话,数据的顺序和原来的顺序会相反(这是在debug的时候发现的,具体原因也没深究),所以采取倒叙遍历 for (int i = detailData.size() - 1; i >= 0; i--) { //根据数据长度创建对应行数 XWPFTableRow insertNewTableRow = table.insertNewTableRow(2); for (int j = 0; j < 5; j++) { //根据列的数量创建对应单元格 insertNewTableRow.createCell(); } // 单行渲染数据 TableRenderPolicy.Helper.renderRow(table.getRow(2), detailData.get(i)); }

下面就开始合并同一列下的数据相同的单元格

//收集操作列的全部数据,放在List中(我这里需要操作的是第2列数据getCells().get(1)) List list = new ArrayList(); HashMap nameNumMap = new HashMap(); for (int i = 0; i < detailData.size(); i++) { String typeName = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString(); list.add(typeName); } //筛选出不同的数据重新放在新list中 List collect = list.stream().distinct().collect(Collectors.toList()); //统计不同数据在全部数据中出现的次数num,并整合放在map中,后面合并的行数需要用到num for (String s : collect) { for (int i = 0; i < detailData.size(); i++) { String typeName1 = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString(); if (s == typeName1) { num++; } } nameNumMap.put(s, num); //每统计完一个,需要重置num num = 0; } //开始合并 for (String s : collect) { //从我们map中取出刚才放入的单位的个数 Integer change = Integer.parseInt(String.valueOf(nameNumMap.get(s))); //开始循环数据 //元素第一次出现的位置 int firstLocation = list.lastIndexOf(s) + 1; int fromRow = firstLocation - change + 2; int toRow = list.lastIndexOf(s) + 2; //由于TableTools.mergeCellsVertically中参数toRow要大于fromRow,否则会报错,所以num>1的才参与合并 if (change > 1) { TableTools.mergeCellsVertically(table, 1, fromRow, toRow); } }



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭