Layout Mode
TableSheet supports three different Group Layouts, which can be set by groupLayout:
Group Layout Mode:
Tabular
Outline
Condensed
Group Fields
Users can set up multiple group fields at the same time, or for each field.
Spacing
The customer could show the spacing to separate the root group level items with the spacing.
Spacing is only useful in Outline and Condensed modes.
Multiple Group Fields
Multiple group headings can be added, with different levels of indentation for the content of the grouped items.
Summary Fields Options
Users can set the content of each field.
/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
import { Component, NgModule, enableProdMode } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { SpreadSheetsModule } from '@mescius/spread-sheets-angular';
import GC from '@mescius/spread-sheets';
import "@mescius/spread-sheets-tablesheet";
import './styles.css';
declare var SplitView: any;
declare let orderDataSource: any;
@Component({
selector: 'app-component',
templateUrl: 'src/app.component.html'
})
export class AppComponent {
hostStyle = {
width: '100%',
height: '100%',
overflow: 'hidden',
float: 'left'
};
sheet!: GC.Spread.Sheets.TableSheet.TableSheet;
selectedTab: number = 0;
tableSheetGroupLayoutMode: number = 1;
position: string = "header";
OutlineAndCondensedGroup = [
{
field: "Office",
caption: "OFFICE",
style: { foreColor: '#000000', backColor: '#ededed', fontSize: "20px", cellPadding: "16 0 0 0" },
headerStyle: { font: "10px Arial", foreColor: "#666", cellPadding: "2 0 0 0" },
summaryFields: [
{
caption: "COUNT",
formula: "=COUNTA([OrderID])",
style: { foreColor: "rgb(185, 122, 87)", fontSize: "20px", cellPadding: "16 0 0 0" },
headerStyle: { font: "10px Arial", foreColor: "#666", cellPadding: "2 0 0 0" }
},
{
caption: "TOTAL AMOUNT",
formula: '=SUM([Amount])',
relateTo: "Amount",
style: { formatter: "$ #,##0.00", cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
},
{
caption: "Σ(Quantity)",
formula: "=SUM([Quantity])",
style: { cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
},
]
},
{
field: "OrderDate",
spacing: { row: 20 },
caption: "ORDER DATE",
style: { foreColor: '#000000', backColor: '#f7f7f7', fontSize: "20px", cellPadding: "16 0 0 0" },
headerStyle: { font: "10px Arial", foreColor: "#666", cellPadding: "2 0 0 0" },
summaryFields: [
{
caption: "SUBTOTAL AMOUNT",
formula: '=SUM([Amount])',
position: "footer",
relateTo: "Amount",
style: { formatter: "$ #,##0.00", cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
},
{
caption: "SUBTOTAL COUNT",
formula: "=SUM([Quantity])",
position: "footer",
style: { cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
}
]
}
]
TabularGroup = [
{
field: "Office",
caption: "OFFICE",
style: { foreColor: '#000000', backColor: '#ededed', fontSize: "20px" },
headerStyle: { font: "10px Arial", foreColor: "#666" },
summaryFields: [
{
caption: "COUNT",
formula: "=COUNTA([OrderID])",
style: { foreColor: "rgb(185, 122, 87)", fontSize: "20px" },
headerStyle: { font: "10px Arial", foreColor: "#666" }
},
{
caption: "TOTAL AMOUNT",
formula: '=SUM([Amount])',
relateTo: "Amount",
style: { formatter: "$ #,##0.00" },
},
{
caption: "Σ(Quantity)",
formula: "=SUM([Quantity])",
},
]
},
{
field: "OrderDate",
spacing: { row: 20 },
caption: "ORDER DATE",
style: { foreColor: '#000000', backColor: '#f7f7f7', fontSize: "20px" },
headerStyle: { font: "10px Arial", foreColor: "#666" },
summaryFields: [
{
caption: "SUBTOTAL AMOUNT",
formula: '=SUM([Amount])',
position: "footer",
relateTo: "Amount",
style: { formatter: "$ #,##0.00" },
},
{
caption: "SUBTOTAL COUNT",
formula: "=SUM([Quantity])",
position: "footer",
}
]
}
]
constructor() {
}
initSpread($event: any) {
let spread = $event.spread;
let self = this;
spread.suspendPaint();
spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader;
spread.options.scrollByPixel = true;
spread.options.scrollPixel = 5;
//init a data manager
var dataManager = spread.dataManager();
var ordersTable = dataManager.addTable("ordersTable", {
data: orderDataSource,
schema: {
type: "csv",
columns: {
OrderDate: { dataType: "date" },
ShipDate: { dataType: "date" },
Quantity: { dataType: "number" },
Amount: { dataType: "number" }
}
}
});
//init a table sheet
var sheet = spread.addSheetTab(0, "TableSheet1", GC.Spread.Sheets.SheetType.tableSheet);
self.sheet = sheet;
sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
sheet.options.allowAddNew = false; //hide new row
sheet.options.groupLayout.mode = GC.Spread.Sheets.TableSheet.GroupLayoutMode.outline; // apply the outline group layout mode
sheet.options.showRowNumber = true;
sheet.applyTableTheme(GC.Spread.Sheets.Tables.TableThemes.light1);
sheet.options.alternatingRowOptions = {
step: [1, 1],
style: new GC.Spread.Sheets.Style("#ffffff")
};
//bind a view to the table sheet
ordersTable.fetch().then(function () {
var myView = ordersTable.addView("myView", [
{ value: "OrderID", width: 180, style: { formatter: "O00000" } },
{ value: "Product", width: 200 },
{ value: "Quantity", width: 100 },
{ value: "OrderDate", width: 100, visible: false },
{ value: "ShipDate", width: 100, visible: false },
{ value: "Office", width: 100 },
{ value: "Category", width: 150 },
{ value: "Amount", width: 120 },
]);
sheet.setDataView(myView);
//init a table sheet panel
var host = document.getElementById("panel");
var panel = new GC.Spread.Sheets.TableSheet.TableSheetPanel("myPanel", sheet, host);
sheet.groupBy(self.OutlineAndCondensedGroup);
});
spread.resumePaint();
initSplitView(spread);
}
resetGroupLayout(mode: any, position: any) {
this.sheet.options.groupLayout = {
mode: mode,
position: position
};
if (mode === 0) {
this.sheet.groupBy(this.TabularGroup);
} else {
this.sheet.groupBy(this.OutlineAndCondensedGroup);
}
}
onTableSheetGroupLayoutModeChange ($event: any) {
this.tableSheetGroupLayoutMode = +$event.target.value;
this.resetGroupLayout(+$event.target.value, this.position);
}
onTableSheetGroupLayoutPositionChange ($event: any) {
this.position = $event.target.value;
this.resetGroupLayout(this.tableSheetGroupLayoutMode, $event.target.value);
}
selectTab(index: number): void {
this.selectedTab = index;
}
}
function initSplitView(spread: any) {
var host = document.getElementById("split-view");
var content = host.getElementsByClassName("split-content")[0];
var panel = host.getElementsByClassName("split-panel")[0];
new SplitView({
host: host,
content: content,
panel: panel,
refreshContent: function () {
spread.refresh();
},
defaultPanelWidth: 320,
allowResize: false
});
}
@NgModule({
imports: [BrowserModule, SpreadSheetsModule],
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/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/spread/source/splitView/splitView.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/fesm2015/zone.min.js"></script>
<!-- SystemJS -->
<script src="$DEMOROOT$/en/angular/node_modules/systemjs/dist/system.js"></script>
<script src="$DEMOROOT$/spread/source/data/orderDataSource.js" type="text/javascript"></script>
<script src="systemjs.config.js"></script>
<!-- plugins -->
<script src="$DEMOROOT$/spread/source/splitView/SplitView.js"></script>
<script>
// workaround to load 'rxjs/operators' from the rxjs bundle
System.import('rxjs').then(function (m) {
System.import('@angular/compiler');
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 id="split-view" class="sample-tutorial">
<gc-spread-sheets class="sample-spreadsheets split-content" [hostStyle]="hostStyle"
(workbookInitialized)="initSpread($event)">
</gc-spread-sheets>
<div class="split-panel">
<div class="split-tabs">
<button class="split-tab-link" [class.active]="selectedTab === 0" (click)="selectTab(0)">TableSheet Panel</button>
<button class="split-tab-link" [class.active]="selectedTab === 1" (click)="selectTab(1)">Setting</button>
</div>
<div class="split-panels">
<div id="panel" class="split-tab-content container" [class.active]="selectedTab === 0"></div>
<div id="settings" class="split-tab-content options-container" [class.active]="selectedTab === 1">
<fieldset>
<legend>Group Layout Mode</legend>
<select id="tableSheetGroupLayoutMode" [(ngModel)]="tableSheetGroupLayoutMode" (change)="onTableSheetGroupLayoutModeChange($event)">
<option value="0">Tabular</option>
<option value="1" selected>Outline</option>
<option value="2">Condensed</option>
</select>
</fieldset>
<fieldset>
<legend>Default Summary Position</legend>
<select id="tableSheetGroupLayoutPosition" [(ngModel)]="position" (change)="onTableSheetGroupLayoutPositionChange($event)">
<option value="header" selected>Header</option>
<option value="footer">Footer</option>
</select>
</fieldset>
</div>
</div>
</div>
</div>
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
}
.sample-spreadsheets {
height: 100%;
overflow: hidden;
float: left;
}
.container {
width: 300px;
height: 100%;
float: left;
border: 1px solid lightgrey;
}
fieldset select {
margin-top: 6px;
padding: 4px 6px;
width: 125px;
}
fieldset input {
margin-top: 6px;
padding: 4px 6px;
width: 110px;
}
.split-panels {
height: 535px;
}
.tab-container {
width: 50%;
margin: 0 auto;
}
.split-tabs {
position: absolute;
top: 12px;
right: 5px;
display: flex;
justify-content: flex-start;
flex-direction: row;
align-items: center;
}
.split-tab-link {
height: 30px;
background-color: #f1f1f1;
border: none;
cursor: pointer;
transition: background-color 0.3s;
margin-bottom: 10px;
}
.split-tab-link:hover {
background-color: #ddd;
}
.split-tab-link.active {
background-color: #ccc;
}
.split-tab-content{
display: none;
}
.split-tab-content.active {
display: block;
}
(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/fesm2015/zone.min.js',
'rxjs': 'npm:rxjs/dist/bundles/rxjs.umd.min.js',
'@angular/core': 'npm:@angular/core/fesm2022',
'@angular/common': 'npm:@angular/common/fesm2022/common.mjs',
'@angular/compiler': 'npm:@angular/compiler/fesm2022/compiler.mjs',
'@angular/platform-browser': 'npm:@angular/platform-browser/fesm2022/platform-browser.mjs',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/fesm2022/platform-browser-dynamic.mjs',
'@angular/common/http': 'npm:@angular/common/fesm2022/http.mjs',
'@angular/router': 'npm:@angular/router/fesm2022/router.mjs',
'@angular/forms': 'npm:@angular/forms/fesm2022/forms.mjs',
'jszip': 'npm:jszip/dist/jszip.min.js',
'typescript': 'npm:typescript/lib/typescript.js',
'ts': './plugin.js',
'tslib':'npm:tslib/tslib.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',
'@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js',
'@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js',
'@mescius/spread-sheets-angular': 'npm:@mescius/spread-sheets-angular/fesm2020/mescius-spread-sheets-angular.mjs',
'@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'
},
"node_modules/@angular": {
defaultExtension: 'mjs'
},
"@mescius/spread-sheets-angular": {
defaultExtension: 'mjs'
},
'@angular/core': {
defaultExtension: 'mjs',
main: 'core.mjs'
}
}
});
})(this);