Custom

Sometimes you want to create your own custom cell type. You can draw when the cell is in display mode, customize the editor when the cell is in editing mode, and handle mouse and keyboard interaction by the cell type itself. If the built-in cell types don't support the kind of functionality you are looking for, then creating a custom cell type would be the way to go. There are many different properties and functions that you can overwrite to get specific cells to fit your own requirements.

<p>You can customize the cell type by inheriting <strong>Base</strong>, and implementing the required methods, such as <strong>paint</strong>, <strong>createEditorElement</strong>, <strong>getEditorValue</strong>, and so on. After that you can use your custom cellType. For example:</p> <pre><code class="hljs js language-js"> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyCellType</span>(<span class="hljs-params"></span>) </span>{ } MyCellType.prototype = <span class="hljs-keyword">new</span> GC.Spread.Sheets.CellTypes.Base(); MyCellType.prototype.paint = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">ctx, value, x, y, w, h, style, options</span>) </span>{ <span class="hljs-comment">//Paints a cell on the canvas. </span> }; MyCellType.prototype.createEditorElement = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-comment">//Creates a DOM element then returns it. </span> }; MyCellType.prototype.getEditorValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">editorContext</span>) </span>{ <span class="hljs-comment">//Gets the editor's value. </span> }; MyCellType.prototype.setEditorValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">editorContext, value</span>) </span>{ <span class="hljs-comment">//Sets the editor's value. </span> }; MyCellType.prototype.activateEditor = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">editorContext, cellStyle, cellRect</span>) </span>{ <span class="hljs-comment">//Activates the editor, including setting properties or attributes for the editor and binding events for the editor. </span> }; <span class="hljs-comment">//... the other methods implements</span> sheet.getRange(<span class="hljs-number">-1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">-1</span>, <span class="hljs-number">1</span>).cellType(<span class="hljs-keyword">new</span> MyCellType()); </code></pre>
var spreadNS = GC.Spread.Sheets; window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss")); initSpread(spread); }; //Custom Cell Type function FivePointedStarCellType() { this.size = 10; } FivePointedStarCellType.prototype = new spreadNS.CellTypes.Base(); FivePointedStarCellType.prototype.paint = function (ctx, value, x, y, w, h, style, context) { if (!ctx) { return; } ctx.save(); // draw inside the cell's boundary ctx.rect(x, y, w, h); ctx.clip(); ctx.beginPath(); if (value) { ctx.fillStyle = "orange"; } else { ctx.fillStyle = "gray"; } var size = this.size; var dx = x + w / 2; var dy = y + h / 2; ctx.beginPath(); var dig = Math.PI / 5 * 4; ctx.moveTo(dx + Math.sin(0 * dig) * size, dy + Math.cos(0 * dig) * size); for (var i = 1; i < 5; i++) { ctx.lineTo(dx + Math.sin(i * dig) * size, dy + Math.cos(i * dig) * size); } ctx.closePath(); ctx.fill(); ctx.restore(); }; FivePointedStarCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) { var xm = cellRect.x + cellRect.width / 2, ym = cellRect.y + cellRect.height / 2, size = 10; var info = { x: x, y: y, row: context.row, col: context.col, cellRect: cellRect, sheetArea: context.sheetArea }; if (xm - size <= x && x <= xm + size && ym - size <= y && y <= ym + size) { info.isReservedLocation = true; } return info; }; FivePointedStarCellType.prototype.processMouseUp = function (hitInfo) { var sheet = hitInfo.sheet; if (sheet && hitInfo.isReservedLocation) { var row = hitInfo.row, col = hitInfo.col, sheetArea = hitInfo.sheetArea; var newValue = !sheet.getValue(row, col, sheetArea); var spread = sheet.getParent(); spread.commandManager().execute({cmd: "editCell", sheetName: sheet.name(), row: row, col: col, newValue: newValue}); return true; } return false; }; function FullNameCellType() { } FullNameCellType.prototype = new spreadNS.CellTypes.Base(); FullNameCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) { if (value) { spreadNS.CellTypes.Base.prototype.paint.apply(this, [ctx, value.firstName + "." + value.lastName, x, y, w, h, style, options]); } }; FullNameCellType.prototype.updateEditor = function(editorContext, cellStyle, cellRect) { if (editorContext) { editorContext.style.width=cellRect.width; editorContext.style.height=100; return {height: 100}; } }; FullNameCellType.prototype.createEditorElement = function () { var div = document.createElement("div"); div.setAttribute("gcUIElement", "gcEditingInput"); div.style.backgroundColor= "white"; div.style.overflow= "hidden"; var span1 = document.createElement('span'); span1.style.display = "block"; var span2 = document.createElement("span"); span2.style.display = "block"; var input1 = document.createElement("input"); var input2 = document.createElement("input"); var type = document.createAttribute('type'); type.nodeValue="text"; var clonedType = type.cloneNode(true); input1.setAttributeNode(type); input2.setAttributeNode(clonedType); div.appendChild(span1); div.appendChild(input1); div.appendChild(span2); div.appendChild(input2); return div; }; FullNameCellType.prototype.getEditorValue = function (editorContext) { if (editorContext && editorContext.children.length === 4) { var input1 = editorContext.children[1]; var firstName = input1.value; var input2 = editorContext.children[3]; var lastName = input2.value; return { firstName: firstName, lastName: lastName }; } }; FullNameCellType.prototype.setEditorValue = function (editorContext, value) { if (editorContext && editorContext.children.length === 4) { var span1 = editorContext.children[0]; span1.innerHTML="First Name:"; var span2 = editorContext.children[2]; span2.innerHTML="Last Name:"; if (value) { var input1 = editorContext.children[1]; input1.value=value.firstName; var input2 = editorContext.children[3]; input2.value=value.lastName; } } }; FullNameCellType.prototype.isReservedKey = function (e) { //cell type handle tab key by itself return (e.keyCode === GC.Spread.Commands.Key.tab && !e.ctrlKey && !e.shiftKey && !e.altKey); }; FullNameCellType.prototype.isEditingValueChanged = function(oldValue, newValue) { if (newValue.firstName != oldValue.firstName || newValue.lastName != oldValue.lastName) { return true; } return false; }; function initSpread(spread) { var sheet = spread.getSheet(0); sheet.suspendPaint(); sheet.setColumnWidth(0, 100); sheet.setColumnWidth(1, 170); var columnInfo = [ { name: "result", displayName: "Result", cellType: new FivePointedStarCellType(), size: 50 }, { name: "person", displayName: "Person", cellType: new FullNameCellType(), size: 170 } ]; var source = [ { result: true, person: {firstName:"LeBron",lastName:"James"}}, { result: false, person: { firstName: "Chris", lastName: "Bosh" } }, { result: true, person: { firstName: "Dwyane", lastName: "Wade" } }, { result: false, person: { firstName: "Mike", lastName: "Miller" } }, { result: true, person: { firstName: "Mike", lastName: "Miller" } }, { result: true, person: { firstName: "Udonis", lastName: "Haslem" } }, { result: true, person: { firstName: "Mario", lastName: "Chalmers" } }, { result: true, person: { firstName: "Joel", lastName: "Anthony" } }, { result: false, person: { firstName: "Shane", lastName: "Battier" } }, { result: false, person: { firstName: "Ray", lastName: "Allen" } }, { result: true, person: { firstName: "James", lastName: "Jones" } }, { result: false, person: { firstName: "Rashard", lastName: "Lewis" } }, { result: true, person: { firstName: "Norris", lastName: "Cole" } }, { result: true, person: { firstName: "Chris", lastName: "Andersen" } }, { result: false, person: { firstName: "Jarvis", lastName: "Varnado" } }, { result: true, person: { firstName: "Juwan", lastName: "Howard" } }, ]; sheet.setDataSource(source); sheet.bindColumns(columnInfo); sheet.resumePaint(); };
<!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/purejs/node_modules/@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/en/purejs/node_modules/@grapecity/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" style="width:100%; height: 100%"></div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }