• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

poi-tl1.10.0动态合并同列不同行单元格动态数据

武飞扬头像
Hx_try
帮助1

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

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

学新通
  1.  
    package com.cantai.qmsat.utils.poi;
  2.  
     
  3.  
    import com.cantai.qmsat.at.operate.entity.InstrumentEntity;
  4.  
    import com.deepoove.poi.data.CellRenderData;
  5.  
    import com.deepoove.poi.data.RowRenderData;
  6.  
    import com.deepoove.poi.policy.DynamicTableRenderPolicy;
  7.  
    import com.deepoove.poi.policy.TableRenderPolicy;
  8.  
    import com.deepoove.poi.util.TableTools;
  9.  
    import org.apache.poi.xwpf.usermodel.XWPFTable;
  10.  
    import org.apache.poi.xwpf.usermodel.XWPFTableCell;
  11.  
    import org.apache.poi.xwpf.usermodel.XWPFTableRow;
  12.  
     
  13.  
    import java.util.ArrayList;
  14.  
    import java.util.HashMap;
  15.  
    import java.util.HashSet;
  16.  
    import java.util.List;
  17.  
    import java.util.stream.Collectors;
  18.  
     
  19.  
    /**
  20.  
    * @author shijin
  21.  
    * @create 2022-11-04 19:30
  22.  
    */
  23.  
    public class RowspanPolicy extends DynamicTableRenderPolicy {
  24.  
     
  25.  
    @Override
  26.  
    public void render(XWPFTable table, Object data) throws Exception {
  27.  
    int num = 0;
  28.  
    if (null == data) return;
  29.  
    List<RowRenderData> detailData = (List<RowRenderData>) data;
  30.  
    if (null != detailData) {
  31.  
    table.removeRow(2);
  32.  
    // 循环插入行,必须采用这种遍历,不然数据会反过来
  33.  
    for (int i = detailData.size() - 1; i >= 0; i--) {
  34.  
    //根据数据长度创建对应行数
  35.  
    XWPFTableRow insertNewTableRow = table.insertNewTableRow(2);
  36.  
    for (int j = 0; j < 5; j ) {
  37.  
    //根据列的数量创建对应单元格
  38.  
    insertNewTableRow.createCell();
  39.  
    }
  40.  
    // 单行渲染
  41.  
    TableRenderPolicy.Helper.renderRow(table.getRow(2), detailData.get(i));
  42.  
    }
  43.  
    //遍历完整个图表之后再合并
  44.  
    List<String> list = new ArrayList<>();
  45.  
    HashMap<String, Object> nameNumMap = new HashMap<>();
  46.  
    for (int i = 0; i < detailData.size(); i ) {
  47.  
    String typeName = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString();
  48.  
    list.add(typeName);
  49.  
    }
  50.  
    List<String> collect = list.stream().distinct().collect(Collectors.toList());
  51.  
    for (String s : collect) {
  52.  
    for (int i = 0; i < detailData.size(); i ) {
  53.  
    String typeName1 = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString();
  54.  
    if (s == typeName1) {
  55.  
    num ;
  56.  
    }
  57.  
    }
  58.  
    nameNumMap.put(s, num);
  59.  
    num = 0;
  60.  
    }
  61.  
    //开始合并
  62.  
    for (String s : collect) {
  63.  
    //从我们map中取出刚才放入的单位的个数
  64.  
    Integer change = Integer.parseInt(String.valueOf(nameNumMap.get(s)));
  65.  
    //开始循环数据
  66.  
    //元素第一次出现的位置
  67.  
    int firstLocation = list.lastIndexOf(s) 1;
  68.  
    int fromRow = firstLocation - change 2;
  69.  
    int toRow = list.lastIndexOf(s) 2;
  70.  
    if (change > 1) {
  71.  
    TableTools.mergeCellsVertically(table, 1, fromRow, toRow);
  72.  
    }
  73.  
    }
  74.  
    }
  75.  
    }
  76.  
    }
学新通
  1. 创建一个类RowspanPolicy继承DynamicTableRenderPolicy,重写render方

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

  1.  
    for (AfTtiInstrumentVo afTtiInstrumentVo : instrumentVos) {
  2.  
    int i = instrumentVos.indexOf(afTtiInstrumentVo) 1;
  3.  
    DateFormat cst = new SimpleDateFormat("yyyy-MM-dd");
  4.  
    DateFormat gmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
  5.  
    Date date1 = gmt.parse(afTtiInstrumentVo.getNextCalibrationDate().toString());
  6.  
    String date2 = cst.format(date1);
  7.  
    RowRenderData rowRenderData = Rows.of(Integer.toString(i), afTtiInstrumentVo.getTestName(), afTtiInstrumentVo.getDeviceName(), afTtiInstrumentVo.getFactoryNumber(), date2).center().create();
  8.  
    instrumentList1.add(rowRenderData);
  9.  
    }
  1. 数据准备好之后,开始重写DynamicTableRenderPolicy策略接口,首先是将数据逐个添加到每一个的单元格,如下:

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

  1.  
    //收集操作列的全部数据,放在List中(我这里需要操作的是第2列数据getCells().get(1))
  2.  
    List<String> list = new ArrayList<>();
  3.  
    HashMap<String, Object> nameNumMap = new HashMap<>();
  4.  
    for (int i = 0; i < detailData.size(); i ) {
  5.  
    String typeName = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString();
  6.  
    list.add(typeName);
  7.  
    }
  8.  
    //筛选出不同的数据重新放在新list中
  9.  
    List<String> collect = list.stream().distinct().collect(Collectors.toList());
  10.  
    //统计不同数据在全部数据中出现的次数num,并整合放在map中,后面合并的行数需要用到num
  11.  
    for (String s : collect) {
  12.  
    for (int i = 0; i < detailData.size(); i ) {
  13.  
    String typeName1 = detailData.get(i).getCells().get(1).getParagraphs().get(0).getContents().get(0).toString();
  14.  
    if (s == typeName1) {
  15.  
    num ;
  16.  
    }
  17.  
    }
  18.  
    nameNumMap.put(s, num);
  19.  
    //每统计完一个,需要重置num
  20.  
    num = 0;
  21.  
    }
  22.  
    //开始合并
  23.  
    for (String s : collect) {
  24.  
    //从我们map中取出刚才放入的单位的个数
  25.  
    Integer change = Integer.parseInt(String.valueOf(nameNumMap.get(s)));
  26.  
    //开始循环数据
  27.  
    //元素第一次出现的位置
  28.  
    int firstLocation = list.lastIndexOf(s) 1;
  29.  
    int fromRow = firstLocation - change 2;
  30.  
    int toRow = list.lastIndexOf(s) 2;
  31.  
    //由于TableTools.mergeCellsVertically中参数toRow要大于fromRow,否则会报错,所以num>1的才参与合并
  32.  
    if (change > 1) {
  33.  
    TableTools.mergeCellsVertically(table, 1, fromRow, toRow);
  34.  
    }
  35.  
    }
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfkjhak
系列文章
更多 icon
同类精品
更多 icon
继续加载