skip to Main Content

My goal is to merge rows for the first 3 columns of my table but if the first column has a different value, my second column should not merge.

To visualize better here is my current table:

https://imgur.com/uGcr54O

And I want to make it look like this:

https://imgur.com/8ibuvoU

As you can see on the first image, BBB1 is merged 4x because it appeared on my query 4x, but since it has a different value on the first column, I need to merge it like it shows on the 2nd image.

Here’s my current code:

<script>
        var table = document.getElementById('myTable');

        function mergeCells(table, startIndex) {
          let headerCell = null;

          for (let row of table.rows) {
            const firstCell = row.cells[startIndex];

            if (headerCell === null || firstCell.innerText !== headerCell.innerText) {
              headerCell = firstCell;
            } else {
              headerCell.rowSpan++;
              firstCell.remove();
            }
          }
        }
        mergeCells(table, 2);
        mergeCells(table, 1);
        mergeCells(table, 0);
</script>

2

Answers


  1. I changed condition to concatenate current column text and previous column text, and compare with next row like "AAA1BBB1" === "AAA2BBB1".
    I think make more simply using jquery.

    <script>
      var table = document.getElementById('myTable');
    
      function mergeCells(table, startIndex) {
        let headerCell = null;
    
        for (let [idx, row] of Object.entries(table.rows)) {
          const firstCell = row.cells[startIndex];
          const prevCell = row.cells[startIndex - 1];
          const lower = table.rows[[parseInt(idx) + 1]];
          const next_firstCell = lower?.cells[startIndex];
          const next_prevCell = lower?.cells[startIndex - 1];
    
          const cur = prevCell?.innerText + firstCell.innerText;
          const next = next_prevCell?.innerText + next_firstCell?.innerText;
    
          if (headerCell === null || cur === next) {
            headerCell = firstCell;
          } else {
            headerCell.rowSpan++;
            firstCell.remove();
          }
        }
      }
      mergeCells(table, 2);
      mergeCells(table, 1);
      mergeCells(table, 0);
    </script>
    
    Login or Signup to reply.
  2. You can merge cells in one column only if the corresponding cells in all previous columns have also been merged. The following code works recursively: after mergeable cells from row M to row N in one column have been determined, it invokes itself to process the cells in these rows in the next column and only then merges the mergeable cells.

    function mergeCells(table, startCol, endCol, startRow, endRow) {
      let cell, cellStart;
    
      function mergeCell(r) {
        if (cell && r > cellStart + 1) {
          if (startCol < endCol)
            mergeCells(table, startCol + 1, endCol, cellStart, r);
          cell.rowSpan = r - cellStart;
          for (let s = cellStart + 1; s < r; s++)
            table.rows[s].cells[startCol].remove();
        }
      }
      for (let r = startRow; r < endRow; r++) {
        const curCell = table.rows[r].cells[startCol];
        if (!cell || cell.textContent !== curCell.textContent) {
          mergeCell(r);
          cell = curCell;
          cellStart = r;
        }
      }
      mergeCell(endRow);
    }
    const table = document.getElementById('myTable');
    mergeCells(table, 0, 2, 1, table.rows.length);
    <table id="myTable">
      <tr>
        <th>Column 1</th>
        <th>Column 2</th>
        <th>Column 3</th>
        <th>Column 4</th>
      </tr>
      <tr>
        <td>AAAA</td>
        <td>BBBB</td>
        <td>CCCC</td>
        <td>DDDD</td>
      </tr>
      <tr>
        <td>AAAA</td>
        <td>BBBB</td>
        <td>CCCC</td>
        <td>DDDD</td>
      </tr>
      <tr>
        <td>AAA1</td>
        <td>BBB1</td>
        <td>CCC1</td>
        <td>DDD2</td>
      </tr>
      <tr>
        <td>AAA1</td>
        <td>BBB1</td>
        <td>CCC1</td>
        <td>DDD3</td>
      </tr>
      <tr>
        <td>AAA2</td>
        <td>BBB1</td>
        <td>CCC3</td>
        <td>DDD4</td>
      </tr>
      <tr>
        <td>AAA2</td>
        <td>BBB1</td>
        <td>CCC3</td>
        <td>DDD5</td>
      </tr>
    </table>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search