Angular Data GridMerge cells

Merge adjacent cells, using the Ctrl+M shortcut or the context menu. Control merged cells, using Handsontable's API.

Overview

By merging, you can combine two or more adjacent cells into a single cell that spans several rows or columns.

Handsontable merges cells in the same way as Microsoft Excel: keeps only the upper-left value of the selected range and clears other values.

Cell merging happens on Handsontable's visual layer and doesn't affect your source data structure.

How to merge cells

To enable the merge cells feature, set the mergeCells option to true or to an array.

To initialize Handsontable with predefined merged cells, provide merged cells details in form of an array:

settings = { mergeCells:[{ row: 1, col: 1, rowspan: 2, colspan: 2 }]}

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from '@handsontable/angular-wrapper';

@Component({
  selector: 'example1-merge-cells',
  standalone: false,
  template: ` <div>
    <hot-table [data]="data" [settings]="gridSettings"></hot-table>
  </div>`,
})
export class Example1MergeCellsComponent {

  readonly data = new Array(100) // number of rows
    .fill(null)
    .map((_, row) =>
      new Array(50) // number of columns
        .fill(null)
        .map((_, column) => `${row}, ${column}`)
    );

  readonly gridSettings: GridSettings = {
    height: 320,
    colWidths: 50,
    rowHeaders: true,
    colHeaders: true,
    contextMenu: true,
    mergeCells: [
      { row: 1, col: 1, rowspan: 3, colspan: 3 },
      { row: 3, col: 4, rowspan: 2, colspan: 2 },
      { row: 5, col: 6, rowspan: 3, colspan: 3 },
    ],
    autoWrapRow: true,
    autoWrapCol: true
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';
import { Example1MergeCellsComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ Example1MergeCellsComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ Example1MergeCellsComponent ]
})

export class AppModule { }

Optimizing rendering of the wide/tall merged cells

When cells span thousands of rows or columns, scrolling may feel slower compared to unmerged cells. To improve performance, consider enabling the dedicated virtualization feature for merged cells, which is disabled by default.

To enable the merged cells virtualization mode, enable the virtualized option:

settings = {
  mergeCells: {
    virtualized: true,
    cells: [{ row: 1, col: 1, rowspan: 200, colspan: 2 }],
  },
};

The example below uses virtualized merged cells. It's also recommended to increase the buffer of rendered rows/columns to minimize the flickering effects.

/* file: app.component.ts */
import { Component } from '@angular/core';
import { GridSettings } from '@handsontable/angular-wrapper';

@Component({
  selector: 'example2-merge-cells',
  standalone: false,
  template: ` <div>
    <hot-table [data]="data" [settings]="gridSettings"></hot-table>
  </div>`,
})
export class Example2MergeCellsComponent {

  readonly data = new Array(50) // number of rows
    .fill(null)
    .map((_, row) =>
      new Array(500) // number of columns
        .fill(null)
        .map((_, column) => `${row}, ${column}`)
    );

  readonly gridSettings: GridSettings = {
    height: 320,
    colWidths: 100,
    rowHeaders: true,
    colHeaders: true,
    contextMenu: true,
    mergeCells: {
      virtualized: true,
      cells: [{ row: 1, col: 1, rowspan: 3, colspan: 498 }],
    },
    viewportColumnRenderingOffset: 15,
    viewportColumnRenderingThreshold: 5,
    autoWrapRow: true,
    autoWrapCol: true
  };
}



/* file: app.module.ts */
import { NgModule, ApplicationConfig } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { registerAllModules } from 'handsontable/registry';
import { HOT_GLOBAL_CONFIG, HotGlobalConfig, HotTableModule } from '@handsontable/angular-wrapper';
import { CommonModule } from '@angular/common';
import { NON_COMMERCIAL_LICENSE } from '@handsontable/angular-wrapper';
import { Example2MergeCellsComponent } from './app.component';

// register Handsontable's modules
registerAllModules();

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: HOT_GLOBAL_CONFIG,
      useValue: {
        themeName: 'ht-theme-main',
        license: NON_COMMERCIAL_LICENSE,
      } as HotGlobalConfig
    }
  ],
};

@NgModule({
  imports: [ BrowserModule, HotTableModule, CommonModule ],
  declarations: [ Example2MergeCellsComponent ],
  providers: [...appConfig.providers],
  bootstrap: [ Example2MergeCellsComponent ]
})

export class AppModule { }

Windows macOS Action Excel Sheets
Ctrl+M Ctrl+M Merge or unmerge the selected cells