Auto Merge In Both Row And Column

SpreadJS supports AutoMerge for any cell range. The neighboring cells in both the rows and columns will be merged automatically if their text are same and they are not in any span range.

You can set auto merge using the autoMerge method for both rows and columns. The following code will apply auto merge in column direction preferentially then in row direction. The following code will apply auto merge in row direction preferentially then in column direction. The following code will apply auto merge in column direction. The following code will apply auto merge in row direction.
import * as React from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; import { AppFunc } from './app-func'; // import { App } from './app-class'; // 1. Functional Component sample createRoot(document.getElementById('app')).render(<AppFunc />); // 2. Class Component sample // createRoot(document.getElementById('app')).render(<App />);
import * as React from 'react'; import GC from '@mescius/spread-sheets'; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; let spread = null; export function AppFunc() { const [rangeMergeOption, setRangeMergeOption] = React.useState({ showHorizontalScrollbar: false, showVerticalScrollbar: false, tabStripVisible: false }); const initSpread = (currSpread) => { spread = currSpread; spread.suspendPaint(); let sheet = spread.getActiveSheet(); sheet.defaults.rowHeight = 40; sheet.defaults.colWidth = 100; sheet.defaults.colHeaderRowHeight = 40; sheet.defaults.rowHeaderColWidth = 60; let defaultStyle = sheet.getDefaultStyle(); defaultStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center; defaultStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center; sheet.setDefaultStyle(defaultStyle); ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"].forEach(function (value, index) { sheet.setValue(0, index, value, GC.Spread.Sheets.SheetArea.colHeader); }); ["12:00", "13:00", "14:00", "15:00", "16:00"].forEach(function (value, index) { sheet.setValue(index, 0, value, GC.Spread.Sheets.SheetArea.rowHeader); }); sheet.setArray(0, 0, [ ["Walker", "Morning Show", "Morning Show", "Sport", "Weather", "N/A", "N/A"], ["Today Show", "Today Show", "Sesame Street", "Football", "Market Watch", "N/A", "N/A"], ["Today Show", "Today Show", "Kid Zone", "Football", "Soap Opera", "N/A", "N/A"], ["News", "News", "News", "News", "News", "N/A", "N/A"], ["News", "News", "News", "News", "News", "N/A", "N/A"] ]); //apply auto merge let range = new GC.Spread.Sheets.Range(-1, -1, -1, -1); sheet.autoMerge(range, GC.Spread.Sheets.AutoMerge.AutoMergeDirection.columnRow); spread.resumePaint(); } const switchAutoMergeDirection = (e) => { let range = new GC.Spread.Sheets.Range(-1, -1, -1, -1); let sheet = spread.getActiveSheet(); sheet.suspendPaint(); //remove old auto merge range sheet.autoMerge(range, GC.Spread.Sheets.AutoMerge.AutoMergeDirection.none); //add new auto merge range sheet.autoMerge(range, parseInt(event.target.value)); sheet.resumePaint(); } return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={initSpread} showHorizontalScrollbar={rangeMergeOption.showHorizontalScrollbar} showVerticalScrollbar={rangeMergeOption.showVerticalScrollbar} tabStripVisible={rangeMergeOption.tabStripVisible} > <Worksheet rowCount={5} colCount={7}></Worksheet> </SpreadSheets> </div> <Panel switchAutoMergeDirection={switchAutoMergeDirection}/> </div> ); } function Panel(props) { return( <div class="options-container"> <div class="option-row"> Changes the auto merge direction. <select id="switchAutoMergeDirection" onChange={props.switchAutoMergeDirection}> <option value="0">None</option> <option value="1">column</option> <option value="2">row</option> <option value="3" selected="selected">columnRow</option> <option value="4">rowColumn</option> </select> </div> </div> ); }
import * as React from 'react'; import GC from '@mescius/spread-sheets'; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; const Component = React.Component; export class App extends Component { constructor(props) { super(props); this.spread = null; this.state = { showHorizontalScrollbar: false, showVerticalScrollbar: false, tabStripVisible: false }; } render() { return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread=>this.initSpread(spread)} showHorizontalScrollbar={this.state.showHorizontalScrollbar} showVerticalScrollbar={this.state.showVerticalScrollbar} tabStripVisible={this.state.tabStripVisible} > <Worksheet rowCount={5} colCount={7}></Worksheet> </SpreadSheets> </div> <Panel switchAutoMergeDirection={(e)=>{this.switchAutoMergeDirection(e)}}/> </div> ); } initSpread(spread) { this.spread = spread; spread.suspendPaint(); let sheet = spread.getActiveSheet(); sheet.defaults.rowHeight = 40; sheet.defaults.colWidth = 100; sheet.defaults.colHeaderRowHeight = 40; sheet.defaults.rowHeaderColWidth = 60; let defaultStyle = sheet.getDefaultStyle(); defaultStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center; defaultStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center; sheet.setDefaultStyle(defaultStyle); ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"].forEach(function (value, index) { sheet.setValue(0, index, value, GC.Spread.Sheets.SheetArea.colHeader); }); ["12:00", "13:00", "14:00", "15:00", "16:00"].forEach(function (value, index) { sheet.setValue(index, 0, value, GC.Spread.Sheets.SheetArea.rowHeader); }); sheet.setArray(0, 0, [ ["Walker", "Morning Show", "Morning Show", "Sport", "Weather", "N/A", "N/A"], ["Today Show", "Today Show", "Sesame Street", "Football", "Market Watch", "N/A", "N/A"], ["Today Show", "Today Show", "Kid Zone", "Football", "Soap Opera", "N/A", "N/A"], ["News", "News", "News", "News", "News", "N/A", "N/A"], ["News", "News", "News", "News", "News", "N/A", "N/A"] ]); //apply auto merge let range = new GC.Spread.Sheets.Range(-1, -1, -1, -1); sheet.autoMerge(range, GC.Spread.Sheets.AutoMerge.AutoMergeDirection.columnRow); spread.resumePaint(); } switchAutoMergeDirection(e) { let range = new GC.Spread.Sheets.Range(-1, -1, -1, -1); let sheet = this.spread.getActiveSheet(); sheet.suspendPaint(); //remove old auto merge range sheet.autoMerge(range, GC.Spread.Sheets.AutoMerge.AutoMergeDirection.none); //add new auto merge range sheet.autoMerge(range, parseInt(event.target.value)); sheet.resumePaint(); } } class Panel extends Component{ constructor(props){ super(props); } render(){ return( <div class="options-container"> <div class="option-row"> Changes the auto merge direction. <select id="switchAutoMergeDirection" onChange={(e)=>{this.props.switchAutoMergeDirection(e)}}> <option value="0">None</option> <option value="1">column</option> <option value="2">row</option> <option value="3" selected="selected">columnRow</option> <option value="4">rowColumn</option> </select> </div> </div> ); } }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('$DEMOROOT$/en/lib/react/license.js').then(function () { System.import('./src/app'); }); </script> </head> <body> <div id="app"></div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 5px; margin-top: 10px; } #switchAutoMergeMode { margin: 10px 0px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } #app { height: 100%; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'react': 'npm:react/cjs/react.production.js', 'react-dom': 'npm:react-dom/cjs/react-dom.production.js', 'react-dom/client': 'npm:react-dom/cjs/react-dom-client.production.js', 'scheduler': 'npm:scheduler/cjs/scheduler.production.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);