html中补齐table表格合并导致每行td数量不一致的情况

有一个行列合并的表格如下:

|----|-----|-----|-----|
| 华东 | 100 | 120 | 正常 |
| 华东 | 80 | 90 | 正常 |
| 华北 | 150 | 180 | 良好 |
| 合计 || 330 | 390 |

可以看到表格中每行和每列最多有4个td,实际的html源文件中:

第一行有4个td,第二行只有2个td,第三行4个td,第4行3个td,我需要为每一行或者列增加一些隐藏的td,使每一行的td数量一致,修改前的源文件如下:

html 复制代码
<!DOCTYPE html>                                                                                                                                                                                                              
  <html lang="zh-CN">                                                                                                                                                                                                          
  <head>                                                                                                                                                                                                                       
      <meta charset="UTF-8">
      <title></title>                                                                                                                                                                                              
      <style>     
          table {
              border-collapse: collapse;
              width: 100%;
              max-width: 600px;
          }
          td {
              border: 1px solid #333;
              padding: 10px;
              text-align: center;
          }
      </style>
  </head>
  <body>

  <table>
      <tr>
          <td rowspan="2">华东</td>
          <td>100</td>
          <td>120</td>
          <td rowspan="2">正常</td>
      </tr>
      <tr>
          <td>80</td>
          <td>90</td>
      </tr>
      <tr>
          <td>华北</td>
          <td>150</td>
          <td>180</td>
          <td>良好</td>
      </tr>
      <tr>
          <td colspan="2">合计</td>
          <td>330</td>
          <td>390</td>
      </tr>
  </table>

  </body>
  </html>

思路是读取源文件中td的colspan和rowspan属性,在td后面增加若干个带有display:none的td:

java 复制代码
import com.zhou.util.NumberUtil;
import com.zhou.common.model.Point;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.*;

/**
 * 表格数据读取转换工具类
 * @author lang.zhou
 * @since  2022/7/25 10:17
 */
@Slf4j
public class TableUtil {






    /**
     * 补齐合并导致每行td数量不一致的情况
     * 添加隐藏td用于占位,降低程序处理逻辑的复杂性
     * @return 返回与某个单元格合并行或列的其他单元格坐标集合
     */
    @SneakyThrows
    public static Map<Point,Set<Point>> fixedTd(Element element){
        int colSize = TableUtil.getColSize(element);
        //读取td的style提供给前端
        Map<Integer, String> tdStyle = new HashMap<>();

        Elements rows = element.select("tr");
        Map<Point,Set<Point>> sameCells = new HashMap<>();

        for (int i = 0; i < rows.size(); i++) {
            Element row = rows.get(i);
            lineY(rows, row, colSize,i,colSize, tdStyle,sameCells);
        }
        return sameCells;
    }

    private static void cellX(Elements rows, Element td, int colSize, int rowIndex, int colIndex, Map<Integer, String> tdStyle, Map<Point,Set<Point>> sameCells){
        Integer rowSpan = NumberUtil.safeToInteger(td.attr("rowspan"), 1);
        Point point = new Point(rowIndex, colIndex);
        Set<Point> points = sameCells.computeIfAbsent(point, l -> new LinkedHashSet<>());
        if(rowSpan > 1){
            for (int k = 1; k < rowSpan; k++) {
                String style = tdStyle.getOrDefault(colIndex + k,"");
                Element nextRow = rows.get(rowIndex + k);
                lineY(rows,nextRow,colSize,rowIndex + k,colIndex,tdStyle,sameCells);
                Element e = new Element("td").attr("style", style + ";display:none");
                e.appendElement("p");
                nextRow.insertChildren(colIndex , e);
                points.add(new Point(rowIndex + k, colIndex));
            }
        }
    }

    private static void lineY(Elements rows,Element row, int colSize, int rowIndex, int to, Map<Integer, String> tdStyle, Map<Point,Set<Point>> sameCells){
        for (int i = 0; i < to; i++) {
            Elements select = row.select("td");
            if (i < select.size()) {
                Element td = select.get(i);
                Point point = new Point(rowIndex, i);
                if(sameCells.containsKey(point)){
                    continue;
                }
                sameCells.computeIfAbsent(point, l -> new LinkedHashSet<>());
                i += cellY(rows,td,colSize,rowIndex,i,tdStyle,sameCells);
            }
        }
    }
    private static int cellY(Elements rows, Element td, int colSize, int rowIndex, int colIndex, Map<Integer, String> tdStyle, Map<Point,Set<Point>> sameCells){
        Integer colSpan = NumberUtil.safeToInteger(td.attr("colspan"), 1);
        Integer rowSpan = NumberUtil.safeToInteger(td.attr("rowspan"), 1);
        String style = tdStyle.get(colIndex);
        Point point = new Point(rowIndex,colIndex);
        Set<Point> pointSet = sameCells.computeIfAbsent(point, l -> new LinkedHashSet<>());
        for (int m = 1; m < colSpan; m++) {
            pointSet.add(new Point(rowIndex,colIndex + m));
            Element e = new Element("td").attr("style", style + ";display:none");
            e.appendElement("p");
            td.after(e);
        }
        for (int n = 0; n < rowSpan; n++) {
            Element row = rows.get(rowIndex + n);
            Elements tds = row.select("td");
            Element nd = tds.get(colIndex);
            cellX(rows,nd,colSize,rowIndex + n,colIndex,tdStyle,sameCells);
        }
        return colSpan - 1;
    }

    /**
     * 得到表格最大列数(考虑合并列)
     */
    public static int getColSize(Element table){
        Element row = table.select("tr").first();
        int cnt = 0;
        Elements cols = row.select("td");
        for (int j = 0; j < cols.size(); j ++) {
            Element td = row.select("td").get(j);
            Integer colSpan = NumberUtil.safeToInteger(td.attr("colspan"), 1);
            cnt += colSpan;
        }
        return cnt;
    }

}

补齐隐藏td后的table源文件如下:

html 复制代码
  <table>
      <tr>
          <td rowspan="2">华东</td>
          <td>100</td>
          <td>120</td>
          <td rowspan="2">正常</td>
      </tr>
      <tr>
          <td style="display: none"></td>
          <td>80</td>
          <td>90</td>
          <td style="display: none"></td>
      </tr>
      <tr>
          <td>华北</td>
          <td>150</td>
          <td>180</td>
          <td>良好</td>
      </tr>
      <tr>
          <td colspan="2">合计</td>
          <td style="display: none"></td>
          <td>330</td>
          <td>390</td>
      </tr>
  </table>
相关推荐
小徐_23335 小时前
wot-ui-cli 1.1.0 发布:支持 OpenCode、Antigravity,wot-ui 图标迁移不再靠猜
前端
__zRainy__5 小时前
Node.js Web 框架选型指南:从 Express 到 Hono 的全景对比
前端·node.js·express·koa·nestjs·egg·fastify
西瓜有点饿6 小时前
PostCSS 和 UnoCSS 的作用和区别
前端·postcss
伟大的兔神6 小时前
我做了一个本地优先的 AI 图片工作台:Loomora v1.0.0 正式发布
前端·javascript·vue.js
90后的晨仔7 小时前
uni-app项目 Vue3 状态管理 Pinia 完全指南:从概念到实战的深度解析
前端
90后的晨仔8 小时前
uni-app 在 iOS 平台跳转页面时移除底部安全区域的完整技术指南
前端
用户938515635078 小时前
React + JWT 登录鉴权底层原理与工程化实践
前端·react.js
zww89491118 小时前
家政派单系统开发实战:架构设计与派单算法指南
前端·系统架构
fangzhanpeng1689 小时前
(前端)2.js变量作用域样例
开发语言·前端·javascript
赵广陆9 小时前
企业实战:web服务集成
前端·pycharm·fastapi