The RangeTemplate is a very powerful new feature allowing the user or developer to define a template of cell ranges as a single celltype and apply that template to a cell to load different data into the template. This could include multiple rows and/or columns, for example allowing you to display a card view in one cell.

To create RangeTemplate , follow this example: Here is the api define: The params row, col,rowCount,colCount is optional, they are use for create template range, if those params not set ,RangeTemplate will use the whole sheet ro create template range. Follow is the example: You can customize your bindingPath or formula in template WorkSheet. Then the RangeTemplate will use the cell value as the datasource to resovle the bindingPath or formula the designative range. The range of condition rule, datavalidation, sparkline data range & date range, sparklineEx, formulas refer to cell or range , those all should contian in the template range, otherwise it may makes wrong. Also the spans in template WorkSheet must be completely contained inside the template range. The rangeTemplate not support nest other rangeTemplate, it may loss data or cause endless loop.
<template> <div class="sample-tutorial"> <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread"> </gc-spread-sheets> <div class="options-container"> <div class="option-row"> <p>In this example, you can change the template label text. Switch to the Template sheet, change the Email or Phone text, then press Update RangeTemplate to apply your changes to the template. You can switch back to Sheet1 to view your changes.</p> <input type="button" id="update" value="Update RangeTemplate" v-on:click = "updateRangeCelltype"/> </div> </div> </div> </template> <script> import Vue from 'vue'; import '@grapecity/spread-sheets-vue' import GC from '@grapecity/spread-sheets'; import './styles.css'; let App = Vue.extend({ name: "app", data: function() { return { spread: null, templateSheet: null, renderSheet: null }; }, methods:{ updateRangeCelltype() { let celltype = new GC.Spread.Sheets.CellTypes.RangeTemplate(this.templateSheet); this.renderSheet.setCellType(-1, 0, celltype); }, initSpread(spread) { this.spread = spread; spread.setSheetCount(1); let renderSheet = spread.getActiveSheet(); let templateSheet = new GC.Spread.Sheets.Worksheet(); templateSheet.fromJSON(templatesheetjson); spread.addSheet(1,templateSheet); this.templateSheet = templateSheet; this.renderSheet = renderSheet; renderSheet.suspendPaint(); let celltype = new GC.Spread.Sheets.CellTypes.RangeTemplate(templateSheet); renderSheet.autoGenerateColumns = false; data = this.updateData(renderSheet,data) renderSheet.setDataSource(data); let cardInfo = { displayName: "Person Card", size: 440, value: function (item) { return item; }, cellType: celltype }; renderSheet.defaults.rowHeight = 207; renderSheet.bindColumn(0, cardInfo); renderSheet.bindColumn(1, { displayName: "Name", name: 'fullName', size: 150 }); renderSheet.bindColumn(2, { displayName: "Phone", name: 'phone', size: 150 }); renderSheet.bindColumn(3, { displayName: "Email", name: 'email', size: 360 }); renderSheet.bindColumn(4, { displayName: "Registered Date", name: 'registered.date', size: 240 }); renderSheet.resumePaint(); }, updateData(sheet, data) { data.forEach(obj => { var url = obj.image; obj.image = GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=IMAGE(\"' + url + '\")'); }); return data; } } }); new Vue({ render: h => h(App) }).$mount('#app'); </script>
<!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/vue/node_modules/@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/spread/source/data/rangecelltype-data.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/data/rangecelltype-templatesheet.js" type="text/javascript"></script> <!-- SystemJS --> <script src="$DEMOROOT$/en/vue/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); System.import('$DEMOROOT$/en/lib/vue/license.js'); </script> </head> <body> <div id="app" style="height: 100%;"></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; overflow: auto; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; } .option-row { padding-bottom: 8px; } label { padding-bottom: 4px; display: block; } input { width: 100%; padding: 4px 8px; box-sizing: border-box; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' }, '*.vue': { loader: 'vue-loader' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@grapecity/spread-sheets': 'npm:@grapecity/spread-sheets/index.js', '@grapecity/spread-sheets-vue': 'npm:@grapecity/spread-sheets-vue/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'css': 'npm:systemjs-plugin-css/css.js', 'vue': 'npm:vue/dist/vue.min.js', 'vue-loader': 'npm:systemjs-vue-browser/index.js', 'tiny-emitter': 'npm:tiny-emitter/index.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: 'js' }, rxjs: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' } } }); })(this);