Skip to content

Merge Cells

The Cell Merge feature allows you to combine adjacent body or pinned data cells into a single, larger cell, much like Excelโ€™s merge functionality. Use it to visually group related data within your grid.

For spreadsheet-style headers that span multiple rows or columns, use the Multi Row Headers plugin instead.

const cellMerge = [{ row: 1, column: 1, rowSpan: 2, colSpan: 2, rowType: 'rgRow', colType: 'rgCol' }]

Source code
TypeScript ts
// src/components/cell-merge/CellMerged.ts

import { defineCustomElements } from '@revolist/revogrid/loader';
defineCustomElements(); // Define the custom element
import { useRandomData, currentTheme } from '../composables/useRandomData';
import './CellMerged.css';

import {
  CellMergePlugin,
  ColumnStretchPlugin,
  type MergeData,
} from '@revolist/revogrid-pro';

const { isDark } = currentTheme();
const { createRandomData } = useRandomData();

const initialCellMerge: MergeData[] = [
  { row: 1, column: 0, rowSpan: 3, colSpan: 1, rowType: 'rgRow', colType: 'rgCol' },
];

const mergedCell: MergeData = {
  row: 1,
  column: 1,
  rowSpan: 2,
  colSpan: 2,
  rowType: 'rgRow',
  colType: 'rgCol',
};

export function load(parentSelector: string) {
  const parent = document.querySelector(parentSelector);
  if (!parent) {
    return;
  }
  parent.classList.add('cell-merge-example');
  if (isDark()) {
    parent.classList.add('cell-merge-example--dark');
  } else {
    parent.classList.remove('cell-merge-example--dark');
  }

  const button = document.createElement('button');
  button.className = 'rv-btn mb-2 self-start';
  button.textContent = 'Merge Cell';

  const lineBreak = document.createElement('br');
  const grid = document.createElement('revo-grid');

  grid.source = createRandomData(100);
  // Define columns
  grid.columns = [
    {
      name: '๐Ÿ†” ID',
      prop: 'id',
    },
    {
      name: '๐ŸŽ Fruit',
      prop: 'name',
    },
    {
      name: '๐Ÿ’ฐ Price',
      prop: 'price',
    },
  ];
  // Define plugin
  grid.plugins = [CellMergePlugin, ColumnStretchPlugin];
  
  grid.stretch = 'all';
  grid.cellMerge = initialCellMerge;

  button.addEventListener('click', () => {
    grid.cellMerge = [mergedCell];
  });

  grid.theme = isDark() ? 'darkMaterial' : 'material';
  grid.hideAttribution = true;
  parent.append(button, lineBreak, grid);
}
Vue vue
// src/components/cell-merge/CellMerged.vue

<template>
  <div
    class="cell-merge-example grow flex flex-col gap-2"
    :class="{ 'cell-merge-example--dark': isDark }"
  >
    <button
      class="rv-btn self-start"
      @click="addCellMerge"
    >
      Merge Cell
    </button>

    <br />

    <RevoGrid
      class="grow"
      :theme="isDark ? 'darkMaterial' : 'material'"
      :columns="columns"
      :source="rows"
      :plugins="plugins"
      stretch="all"
      :cell-merge.prop="cellMerge"
      hide-attribution
    />
  </div>
</template>

<script setup lang="ts">
import { ref, shallowRef } from 'vue';
import RevoGrid from '@revolist/vue3-datagrid';
import './CellMerged.css';
import { CellMergePlugin, ColumnStretchPlugin, type MergeData } from '@revolist/revogrid-pro';
import { currentThemeVue, useRandomData } from '../composables/useRandomData';

const { isDark } = currentThemeVue();
const { createRandomData } = useRandomData();

const columns = ref([
  { name: '๐Ÿ†” ID', prop: 'id' },
  { name: '๐ŸŽ Fruit', prop: 'name' },
  { name: '๐Ÿ’ฐ Price', prop: 'price' },
]);

const plugins = ref([CellMergePlugin, ColumnStretchPlugin]);

const rows = ref(createRandomData(100));

const cellMerge = shallowRef<MergeData[]>([
  { row: 1, column: 0, rowSpan: 3, colSpan: 1, rowType: 'rgRow', colType: 'rgCol' },
]);

const addCellMerge = () => {
  cellMerge.value = [{
    row: 1,
    column: 1,
    rowSpan: 2,
    colSpan: 2,
    rowType: 'rgRow',
    colType: 'rgCol',
  }];
};
</script>
React tsx
// src/components/cell-merge/CellMerged.tsx

import { useState, useMemo } from 'react';
import { RevoGrid, type DataType } from '@revolist/react-datagrid';
import './CellMerged.css';
import {
  CellMergePlugin,
  ColumnStretchPlugin,
  type MergeData,
} from '@revolist/revogrid-pro';
import { useRandomData, currentTheme } from '../composables/useRandomData';
const { isDark } = currentTheme();
const { createRandomData } = useRandomData();

const initialCellMerge: MergeData[] = [
  { row: 1, column: 0, rowSpan: 3, colSpan: 1, rowType: 'rgRow', colType: 'rgCol' },
];

const mergedCell: MergeData = {
  row: 1,
  column: 1,
  rowSpan: 2,
  colSpan: 2,
  rowType: 'rgRow',
  colType: 'rgCol',
};

function CellMerged() {
  const [source] = useState<DataType[]>(createRandomData(100));
  const [cellMerge, setCellMerge] = useState<MergeData[]>(initialCellMerge);
  const darkTheme = isDark();

  const columns = useMemo(
    () => [
      { name: '๐Ÿ†” ID', prop: 'id' },
      { name: '๐ŸŽ Fruit', prop: 'name' },
      { name: '๐Ÿ’ฐ Price', prop: 'price' },
    ],
    []
  );

  const handleMergeClick = () => {
    setCellMerge([mergedCell]);
  };

  return (
    <div className={`flex grow flex-col gap-2 cell-merge-example${darkTheme ? ' cell-merge-example--dark' : ''}`}>
      <button className="rv-btn self-start" onClick={handleMergeClick}>
        Merge Cell
      </button>
      <br />
      <RevoGrid
        className='grow'
        columns={columns}
        source={source}
        stretch="all"
        cellMerge={cellMerge}
        hide-attribution
        theme={darkTheme ? 'darkMaterial' : 'material'}
        plugins={[CellMergePlugin, ColumnStretchPlugin]}
      />
    </div>
  );
}

export default CellMerged;
Angular ts
// src/components/cell-merge/CellMergedAngular.ts
import './CellMerged.css';
import {
  Component,
  NO_ERRORS_SCHEMA,
  signal,
  ViewEncapsulation,
} from '@angular/core';
import { RevoGrid } from '@revolist/angular-datagrid';
import {
  CellMergePlugin,
  ColumnStretchPlugin,
  type MergeData,
} from '@revolist/revogrid-pro';
import { useRandomData, currentTheme } from '../composables/useRandomData';

@Component({
  selector: 'cell-merge-grid',
  standalone: true,
  imports: [RevoGrid],
  template: `
    <div
      class="cell-merge-example"
      [class.cell-merge-example--dark]="theme === 'darkMaterial'"
    >
      <button
        class="rv-btn mb-2"
        (click)="mergeCells()">Merge Cell</button>
      <br />
      <revo-grid
        [columns]="columns"
        [source]="source"
        stretch="all"
        [hideAttribution]="true"
        [theme]="theme"
        [plugins]="plugins"
        [cellMerge]="cellMerge()"
        style="min-height: 400px;"
      ></revo-grid>
    </div>`,
  encapsulation: ViewEncapsulation.None,
  schemas: [NO_ERRORS_SCHEMA],
})
export class CellMergeGridComponent {
  theme = currentTheme().isDark() ? 'darkMaterial' : 'material';
  source = useRandomData().createRandomData(100);
  cellMerge = signal<MergeData[]>([
    { row: 1, column: 0, rowSpan: 3, colSpan: 1, rowType: 'rgRow', colType: 'rgCol' },
  ]);

  columns = [
    { name: '๐Ÿ†” ID', prop: 'id' },
    { name: '๐ŸŽ Fruit', prop: 'name' },
    { name: '๐Ÿ’ฐ Price', prop: 'price' },
  ];

  plugins = [CellMergePlugin, ColumnStretchPlugin];

  mergeCells() {
    this.cellMerge.set([{
      row: 1,
      column: 1,
      rowSpan: 2,
      colSpan: 2,
      rowType: 'rgRow',
      colType: 'rgCol',
    }]);
  }
}

Cell Merge is a powerful tool that can help you:

  • Group Data Visually: Highlight or group related data by merging cells, which improves the readability and interpretability of your grid.
  • Data Grouping: Use cell merging to visually segment related data or to emphasize specific sections of your grid.

The Cell Merge feature enables you to specify which cells should be merged into a larger cell. This larger cell will span across multiple columns and/or rows. The content of the merged cell will be centrally displayed, enhancing the layout of your grid.

Since this is a Pro feature, ensure that you have access to the Pro version of RevoGrid to utilize this functionality.