Overview

TableSheet grouping can group a data source by the specified fields.

Besides the basic column, each group can have summary columns, which can use any formula to aggregate the grouped records, such as SUM, AVERAGE, COUNT, COUNTA, MIN or MAX.

Each summary column can also have slice columns, which can slice the aggregation result into several columns.

In addition, the basic column and the summary columns can have captions and the width and style can be changed.

The slice columns have width and styles that can be changed.

Description
app.component.ts
index.html
app.component.html
styles.css
Copy to CodeMine

TableSheet class provides the groupBy method and removeGroupBy method.

  /**
    * group the table sheet by options
    * @param {GC.Spread.Sheets.TableSheet.IGroupByOptions[]} options - The options of the groupBy
    * @returns {GC.Spread.Sheets.TableSheet.IGroupByOptions[]}
    */
   groupBy(options?: GC.Spread.Sheets.TableSheet.IGroupByOptions[]): GC.Spread.Sheets.TableSheet.IGroupByOptions[]

TableSheet could be grouped by a single field.

sheet.groupBy([
    {
        field: "Category"
    }
]);

TableSheet could be grouped by single field, with summary fields and slice fields.

sheet.groupBy([
    {
        caption: "Category", field: "Category", width: 120, style: { backColor: "#D0CECE" }, summaryFields: [
            {
                caption: "SUM(Quantity)",
                formula: "=SUM([Quantity])",
                slice: {field: "Office", width: 120, style: { backColor: "#D9E1F2"} },
                width: 120,
                style: { backColor: "#D9E1F2" }
            },
            {
                caption: "SUM(Amount)",
                formula: "=SUM([Amount])",
                slice: {field: "=YEAR([@OrderDate])", width: 120, style: { backColor: "#E2EFDA", formatter: "$ #,##0.00"} },
                width: 120,
                style: { backColor: "#E2EFDA", formatter: "$ #,##0.00" }
            }
        ]
    }
]);
  /**
   * remove group status of the table sheet
   * @returns {void}
   */
  removeGroupBy(): void

TableSheet could be removed the group status.

sheet.removeGroupBy();
TableSheet class provides the groupBy method and removeGroupBy method. TableSheet could be grouped by a single field. TableSheet could be grouped by single field, with summary fields and slice fields. TableSheet could be removed the group status.
/*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 let orderDataSource: any; @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { hostStyle = { width: 'calc(100% - 210px)', height: '100%', overflow: 'hidden', float: 'left' }; spread: GC.Spread.Sheets.Workbook; constructor() { } initSpread($event: any) { let spread = this.spread = $event.spread; spread.suspendPaint(); spread.clearSheets(); spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader; //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); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet let _this = this; ordersTable.fetch().then(function() { var myView = ordersTable.addView("myView", [ { value: "OrderID", caption: "ID", width: 100 }, { value: "Product", width: 150 }, { value: "OrderDate", caption: "Order Date", width: 105 }, { value: "ShipDate", caption: "Ship Date", width: 105 }, { value: "Quantity", width: 100 }, { value: "Amount", width: 100 }, { value: "Office", width: 100 }, { value: "Category", width: 150 } ]); spread.suspendPaint(); sheet.setDataView(myView); _this.groupCallback(); spread.resumePaint(); }); spread.resumePaint(); } groupCallback() { let sheet = this.spread.getActiveSheetTab(); sheet.groupBy([ { caption: "Category", field: "Category", width: 120, style: { backColor: "#D0CECE" }, summaryFields: [ { caption: "Σ(Quantity)", formula: "=SUM([Quantity])", slice: {field: "Office", width: 70, style: {backColor: "#D9E1F2"}}, width: 105, style: {backColor: "#D9E1F2"} }, { caption: "μ(Amount)", formula: "=AVERAGE([Amount])", slice: {field: "=YEAR([@OrderDate])", width: 80, style: {backColor: "#E2EFDA", formatter: "$ #,##0.00"}}, width: 100, style: {backColor: "#E2EFDA", formatter: "$ #,##0.00"} } ] } ]); } removeGroupCallback() { let sheet = this.spread.getActiveSheetTab(); sheet.removeGroupBy(); } } @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"> <script src="$DEMOROOT$/spread/source/data/orderDataSource.js" type="text/javascript"></script> <!-- 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="systemjs.config.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 class="sample-tutorial"> <gc-spread-sheets [hostStyle]="hostStyle" (workbookInitialized)="initSpread($event)"> </gc-spread-sheets> <div class="options-container"> <div class="option-row"> <label>Use the below buttons to group or ungroup.</label> </div> <div class="option-row"> <input type="button" value="Group" id="groupButton" (click)="groupCallback()"/> <input type="button" value="RemoveGroup" id="removeGroupButton" (click)="removeGroupCallback()"/> </div> </div> </div>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 210px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 210px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 5px; margin-top: 10px; } label { display: block; margin-bottom: 3px; margin-top: 3px; } input { padding: 4px 6px; } input[type=button] { margin-top: 6px; display: block; width: 100%; text-align: center; } input[type=text] { width: 230px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: 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/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);