Custom Merging

By default, the FlexGrid applies merging to cells based on their content. In some cases, you may want to use different strategies for merging.You can achieve this by defining a class that extends the wijmo.grid.MergeManager class and assigning an object of that type to the grid's mergeManager property.

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import * as wjGrid from '@grapecity/wijmo.grid'; import * as wjCore from '@grapecity/wijmo'; export class CustomMergeManager extends wjGrid.MergeManager { constructor(flexGrid) { super(flexGrid); } getMergedRange(panel, r, c, clip = true) { // create basic cell range var rg = new wjGrid.CellRange(r, c); // expand left/right for (var i = rg.col; i < panel.columns.length - 1; i++) { if (panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i + 1, true)) break; rg.col2 = i + 1; } for (var i = rg.col; i > 0; i--) { if (panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i - 1, true)) break; rg.col = i - 1; } // expand up/down for (var i = rg.row; i < panel.rows.length - 1; i++) { if (panel.getCellData(i, rg.col, true) != panel.getCellData(i + 1, rg.col, true)) break; rg.row2 = i + 1; } for (var i = rg.row; i > 0; i--) { if (panel.getCellData(i, rg.col, true) != panel.getCellData(i - 1, rg.col, true)) break; rg.row = i - 1; } // done return rg; } } function setData(p, r, cells) { if (p.cellType == wjGrid.CellType.Cell) { p.grid.rowHeaders.setCellData(r, 0, cells[0]); } for (var i = 1; i < cells.length; i++) { p.setCellData(r, i - 1, cells[i]); } } function centerCell(s, e) { if (e.cell.children.length == 0) { e.cell.innerHTML = '<div>' + e.cell.innerHTML + '</div>'; wjCore.setCss(e.cell, { display: 'table', tableLayout: 'fixed' }); wjCore.setCss(e.cell.children[0], { display: 'table-cell', textAlign: 'center', verticalAlign: 'middle' }); } } // document.readyState === 'complete' ? init() : window.onload = init; // function init() { // create an unbound grid with 5 rows and 7 columns var theGrid = new wjGrid.FlexGrid('#theGrid'); while (theGrid.columns.length < 7) { theGrid.columns.push(new wjGrid.Column()); } while (theGrid.rows.length < 5) { theGrid.rows.push(new wjGrid.Row()); } // configure the grid theGrid.mergeManager = new CustomMergeManager(theGrid); theGrid.formatItem.addHandler(centerCell); theGrid.rowHeaders.columns[0].width = 80; theGrid.rows.defaultSize = 40; theGrid.alternatingRowStep = 0; theGrid.isReadOnly = true; // populate the grid setData(theGrid.columnHeaders, 0, ',Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday'.split(',')); setData(theGrid.cells, 0, '12:00,Walker,Morning Show,Morning Show,Sport,Weather,N/A,N/A'.split(',')); setData(theGrid.cells, 1, '13:00,Today Show,Today Show,Sesame Street,Football,Market Watch,N/A,N/A'.split(',')); setData(theGrid.cells, 2, '14:00,Today Show,Today Show,Kid Zone,Football,Soap Opera,N/A,N/A'.split(',')); setData(theGrid.cells, 3, '15:00,News,News,News,News,News,N/A,N/A'.split(',')); setData(theGrid.cells, 4, '16:00,News,News,News,News,News,N/A,N/A'.split(',')); } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid Custom Merging</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <div id="theGrid"> </div> </div> </body> </html> .wj-flexgrid { margin-bottom: 12px; } body { margin-bottom: 24px; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; // import * as wjCore from '@grapecity/wijmo'; import * as wjGrid from '@grapecity/wijmo.grid'; import { Component, enableProdMode, NgModule } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { WjGridModule } from '@grapecity/wijmo.angular2.grid'; class CustomMergeManager extends wjGrid.MergeManager { constructor(flexGrid: wjGrid.FlexGrid) { super(flexGrid); } getMergedRange(panel: wjGrid.GridPanel, r: number, c: number, clip: boolean = true) { // create basic cell range var rg = new wjGrid.CellRange(r, c); // expand left/right for (var i = rg.col; i < panel.columns.length - 1; i++) { if (panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i + 1, true)) break; rg.col2 = i + 1; } for (var i = rg.col; i > 0; i--) { if (panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i - 1, true)) break; rg.col = i - 1; } // expand up/down for (var i = rg.row; i < panel.rows.length - 1; i++) { if (panel.getCellData(i, rg.col, true) != panel.getCellData(i + 1, rg.col, true)) break; rg.row2 = i + 1; } for (var i = rg.row; i > 0; i--) { if (panel.getCellData(i, rg.col, true) != panel.getCellData(i - 1, rg.col, true)) break; rg.row = i - 1; } // done return rg; } } function setData(p: wjGrid.GridPanel, r: number, cells: string[]) { if (p.cellType == wjGrid.CellType.Cell) { p.grid.rowHeaders.setCellData(r, 0, cells[0]); } for (var i = 1; i < cells.length; i++) { p.setCellData(r, i - 1, cells[i]); } } function centerCell(s: wjCore.IEventHandler, e: any) { if (e.cell.children.length == 0) { e.cell.innerHTML = '<div>' + e.cell.innerHTML + '</div>'; wjCore.setCss(e.cell, { display: 'table', tableLayout: 'fixed' }); wjCore.setCss(e.cell.children[0], { display: 'table-cell', textAlign: 'center', verticalAlign: 'middle' }); } } // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { constructor() { } onInitialized(flexGrid: wjGrid.FlexGrid) { while (flexGrid.columns.length < 7) { flexGrid.columns.push(new wjGrid.Column()); } while (flexGrid.rows.length < 5) { flexGrid.rows.push(new wjGrid.Row()); } // configure the grid flexGrid.mergeManager = new CustomMergeManager(flexGrid); flexGrid.formatItem.addHandler(centerCell); flexGrid.rowHeaders.columns[0].width = 80; flexGrid.rows.defaultSize = 40; flexGrid.alternatingRowStep = 0; flexGrid.isReadOnly = true; // populate the grid setData(flexGrid.columnHeaders, 0, ',Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday'.split(',')); setData(flexGrid.cells, 0, '12:00,Walker,Morning Show,Morning Show,Sport,Weather,N/A,N/A'.split(',')); setData(flexGrid.cells, 1, '13:00,Today Show,Today Show,Sesame Street,Football,Market Watch,N/A,N/A'.split(',')); setData(flexGrid.cells, 2, '14:00,Today Show,Today Show,Kid Zone,Football,Soap Opera,N/A,N/A'.split(',')); setData(flexGrid.cells, 3, '15:00,News,News,News,News,News,N/A,N/A'.split(',')); setData(flexGrid.cells, 4, '16:00,News,News,News,News,News,N/A,N/A'.split(',')); } } //\\ @NgModule({ imports: [WjGridModule, BrowserModule], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } // enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexGrid Custom Merging</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <wj-flex-grid #theGird (initialized)="onInitialized(theGird)"> </wj-flex-grid> </div> .wj-flexgrid { margin-bottom: 12px; } body { margin-bottom: 24px; } <template> <div class="container-fluid"> <wj-flex-grid :initialized="onInitialized"></wj-flex-grid> </div> </template> <script> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import Vue from "vue"; import * as wjCore from "@grapecity/wijmo"; import * as wjGrid from "@grapecity/wijmo.grid"; import "@grapecity/wijmo.vue2.grid"; var __extends = (this && this.__extends) || (function() { var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function(d, b) { d.__proto__ = b; }) || function(d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); }; })(); var CustomMergeManager = (function(_super) { __extends(CustomMergeManager, _super); function CustomMergeManager(flexGrid) { return _super.call(this, flexGrid) || this; } CustomMergeManager.prototype.getMergedRange = function(panel, r, c, clip) { if (clip === void 0) { clip = true; } var rg = new wjGrid.CellRange(r, c); for (var i = rg.col; i < panel.columns.length - 1; i++) { if ( panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i + 1, true) ) break; rg.col2 = i + 1; } for (var i = rg.col; i > 0; i--) { if ( panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i - 1, true) ) break; rg.col = i - 1; } for (var i = rg.row; i < panel.rows.length - 1; i++) { if ( panel.getCellData(i, rg.col, true) != panel.getCellData(i + 1, rg.col, true) ) break; rg.row2 = i + 1; } for (var i = rg.row; i > 0; i--) { if ( panel.getCellData(i, rg.col, true) != panel.getCellData(i - 1, rg.col, true) ) break; rg.row = i - 1; } return rg; }; return CustomMergeManager; })(wjGrid.MergeManager); let App = Vue.extend({ name: "app", methods: { onInitialized: function(flexGrid) { while (flexGrid.columns.length < 7) { flexGrid.columns.push(new wjGrid.Column()); } while (flexGrid.rows.length < 5) { flexGrid.rows.push(new wjGrid.Row()); } // configure the grid flexGrid.mergeManager = new CustomMergeManager(flexGrid); flexGrid.formatItem.addHandler(centerCell); flexGrid.rowHeaders.columns[0].width = 80; flexGrid.rows.defaultSize = 40; flexGrid.alternatingRowStep = 0; flexGrid.isReadOnly = true; // populate the grid setData( flexGrid.columnHeaders, 0, ",Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday".split( "," ) ); setData( flexGrid.cells, 0, "12:00,Walker,Morning Show,Morning Show,Sport,Weather,N/A,N/A".split( "," ) ); setData( flexGrid.cells, 1, "13:00,Today Show,Today Show,Sesame Street,Football,Market Watch,N/A,N/A".split( "," ) ); setData( flexGrid.cells, 2, "14:00,Today Show,Today Show,Kid Zone,Football,Soap Opera,N/A,N/A".split( "," ) ); setData( flexGrid.cells, 3, "15:00,News,News,News,News,News,N/A,N/A".split(",") ); setData( flexGrid.cells, 4, "16:00,News,News,News,News,News,N/A,N/A".split(",") ); } } }); function setData(p, r, cells) { if (p.cellType == wjGrid.CellType.Cell) { p.grid.rowHeaders.setCellData(r, 0, cells[0]); } for (var i = 1; i < cells.length; i++) { p.setCellData(r, i - 1, cells[i]); } } function centerCell(s, e) { if (e.cell.children.length == 0) { e.cell.innerHTML = "<div>" + e.cell.innerHTML + "</div>"; wjCore.setCss(e.cell, { display: "table", tableLayout: "fixed" }); wjCore.setCss(e.cell.children[0], { display: "table-cell", textAlign: "center", verticalAlign: "middle" }); } } new Vue({ render: h => h(App) }).$mount("#app"); </script> <style> .wj-flexgrid { margin-bottom: 12px; } body { margin-bottom: 24px; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AutoComplete</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"> </div> </body> </html> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import "./app.css"; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; // import * as wjCore from "@grapecity/wijmo"; import * as wjcGrid from "@grapecity/wijmo.react.grid"; import * as wjGrid from '@grapecity/wijmo.grid'; class App extends React.Component { constructor(props) { super(props); } render() { return <div className="container-fluid"> <wjcGrid.FlexGrid initialized={this.onInitialized.bind(this)}> </wjcGrid.FlexGrid> </div>; } onInitialized(flexGrid) { while (flexGrid.columns.length < 7) { flexGrid.columns.push(new wjGrid.Column()); } while (flexGrid.rows.length < 5) { flexGrid.rows.push(new wjGrid.Row()); } // configure the grid flexGrid.mergeManager = new CustomMergeManager(flexGrid); flexGrid.formatItem.addHandler(this.centerCell); flexGrid.rowHeaders.columns[0].width = 80; flexGrid.rows.defaultSize = 40; flexGrid.alternatingRowStep = 0; flexGrid.isReadOnly = true; // populate the grid this.setData(flexGrid.columnHeaders, 0, ",Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday".split(",")); this.setData(flexGrid.cells, 0, "12:00,Walker,Morning Show,Morning Show,Sport,Weather,N/A,N/A".split(",")); this.setData(flexGrid.cells, 1, "13:00,Today Show,Today Show,Sesame Street,Football,Market Watch,N/A,N/A".split(",")); this.setData(flexGrid.cells, 2, "14:00,Today Show,Today Show,Kid Zone,Football,Soap Opera,N/A,N/A".split(",")); this.setData(flexGrid.cells, 3, "15:00,News,News,News,News,News,N/A,N/A".split(",")); this.setData(flexGrid.cells, 4, "16:00,News,News,News,News,News,N/A,N/A".split(",")); } setData(p, r, cells) { if (p.cellType == wjGrid.CellType.Cell) { p.grid.rowHeaders.setCellData(r, 0, cells[0]); } for (var i = 1; i < cells.length; i++) { p.setCellData(r, i - 1, cells[i]); } } centerCell(s, e) { if (e.cell.children.length == 0) { e.cell.innerHTML = "<div>" + e.cell.innerHTML + "</div>"; wjCore.setCss(e.cell, { display: "table", tableLayout: "fixed" }); wjCore.setCss(e.cell.children[0], { display: "table-cell", textAlign: "center", verticalAlign: "middle" }); } } } class CustomMergeManager extends wjGrid.MergeManager { constructor(flexGrid) { super(flexGrid); } getMergedRange(panel, r, c, clip = true) { // create basic cell range var rg = new wjGrid.CellRange(r, c); // expand left/right for (var i = rg.col; i < panel.columns.length - 1; i++) { if (panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i + 1, true)) break; rg.col2 = i + 1; } for (var i = rg.col; i > 0; i--) { if (panel.getCellData(rg.row, i, true) != panel.getCellData(rg.row, i - 1, true)) break; rg.col = i - 1; } // expand up/down for (var i = rg.row; i < panel.rows.length - 1; i++) { if (panel.getCellData(i, rg.col, true) != panel.getCellData(i + 1, rg.col, true)) break; rg.row2 = i + 1; } for (var i = rg.row; i > 0; i--) { if (panel.getCellData(i, rg.col, true) != panel.getCellData(i - 1, rg.col, true)) break; rg.row = i - 1; } // done return rg; } } ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Grapecity Wijmo OLAP Pivot Chart Overview</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html> .wj-flexgrid { margin-bottom: 12px; } body { margin-bottom: 24px; }