You can customize the CellType by inheriting Base, and implementing the required methods, such as paint, createEditorElement, getEditorValue, and so on. After that you can use your custom CellType. For example:
// @ts-ignore
import { Component, NgModule, enableProdMode } from '@angular/core';
// @ts-ignore
import { BrowserModule } from '@angular/platform-browser';
// @ts-ignore
import { FormsModule } from '@angular/forms';
// @ts-ignore
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
// @ts-ignore
import { SpreadSheetsModule } from '@grapecity/spread-sheets-angular';
// @ts-ignore
import GC from '@grapecity/spread-sheets';
import { FivePointedStarCellType, FullNameCellType } from "./app.data";
import './styles.css';
const spreadNS = GC.Spread.Sheets;
@Component({
selector: 'app-component',
templateUrl: 'src/app.component.html'
})
export class AppComponent {
spread: GC.Spread.Sheets.Workbook;
hostStyle = {
width: 'calc(100% - 280px)',
height: '100%',
overflow: 'hidden',
float: 'left'
};
initSpread($event: any) {
const sheet = $event.spread.getSheet(0);
sheet.suspendPaint();
sheet.setColumnWidth(0, 100);
sheet.setColumnWidth(1, 170);
const columnInfo = [
{ name: "result", displayName: "Result", cellType: new FivePointedStarCellType(), size: 50 },
{ name: "person", displayName: "Person", cellType: new FullNameCellType(), size: 170 }
];
const 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();
}
}
@NgModule({
imports: [BrowserModule, SpreadSheetsModule, FormsModule],
declarations: [AppComponent],
exports: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
enableProdMode();
// Bootstrap application with hash style navigation and global services.
platformBrowserDynamic().bootstrapModule(AppModule);
<!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/angular/node_modules/@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<!-- Polyfills -->
<script src="$DEMOROOT$/en/angular/node_modules/core-js/client/shim.min.js"></script>
<script src="$DEMOROOT$/en/angular/node_modules/zone.js/dist/zone.min.js"></script>
<!-- SystemJS -->
<script src="$DEMOROOT$/en/angular/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('$DEMOROOT$/en/lib/angular/license.ts');
System.import('./src/app.component');
});
</script>
</head>
<body>
<app-component></app-component>
</body>
</html>
<div class="sample-tutorial">
<gc-spread-sheets [hostStyle]="hostStyle" (workbookInitialized)="initSpread($event)">
<gc-worksheet></gc-worksheet>
</gc-spread-sheets>
</div>
import GC from "@grapecity/spread-sheets";
const spreadNS = GC.Spread.Sheets;
//Custom Cell Type
export class FivePointedStarCellType {
constructor() {
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;
};
export class 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;
};
.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;
}
.sample-options{
z-index: 1000;
}
.option {
padding-bottom: 6px;
}
.checkbox {
padding-right: 12px;
display: inline-block;
}
label {
display: inline-block;
min-width: 100px;
}
input, select {
width: 100%;
padding: 4px 0;
margin-top: 4px;
box-sizing: border-box;
}
input[type=checkbox] {
width: auto;
padding: 0;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
(function (global) {
System.config({
transpiler: 'ts',
typescriptOptions: {
tsconfig: true
},
meta: {
'typescript': {
"exports": "ts"
},
'*.css': { loader: 'css' }
},
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
'core-js': 'npm:core-js/client/shim.min.js',
'zone': 'npm:zone.js/dist/zone.min.js',
'rxjs': 'npm:rxjs/bundles/rxjs.umd.min.js',
'@angular/core': 'npm:@angular/core/bundles/core.umd.min.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.min.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.min.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.min.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.min.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.min.js',
'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.min.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.min.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.min.js',
'jszip': 'npm:jszip/dist/jszip.min.js',
'typescript': 'npm:typescript/lib/typescript.js',
'ts': 'npm:plugin-typescript/lib/plugin.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',
'@grapecity/spread-sheets': 'npm:@grapecity/spread-sheets/index.js',
'@grapecity/spread-sheets-angular': 'npm:@grapecity/spread-sheets-angular/bundles/grapecity-spread-sheets-angular.umd.js',
'@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
src: {
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
},
"node_modules": {
defaultExtension: 'js'
},
}
});
})(this);