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.jsx
app-func.jsx
app-class.jsx
index.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.
import * as React from 'react'; import * as ReactDOM from 'react-dom'; import './styles.css'; import { AppFunc } from './app-func'; import { App } from './app-class'; // 1. Functional Component sample ReactDOM.render(<AppFunc />, document.getElementById('app')); // 2. Class Component sample // ReactDOM.render(<App />, document.getElementById('app'));
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-tablesheet"; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; import './styles.css'; export function AppFunc() { let spread = null; let initSpread = function (value) { spread = value; 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 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); groupCallback(); spread.resumePaint(); }); spread.resumePaint(); } let groupCallback = function() { let sheet = 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"} } ] } ]); } let removeGroupCallback = function() { let sheet = spread.getActiveSheetTab(); sheet.removeGroupBy(); } return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => initSpread(spread)}> </SpreadSheets> </div> <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" onClick={() => groupCallback()}/> <input type="button" value="Remove Group" id="removeGroupButton" onClick={() => removeGroupCallback()}/> </div> </div> </div> ); }
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-tablesheet"; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; import './styles.css'; const Component = React.Component; function _getElementById(id) { return document.getElementById(id); } export class App extends Component { constructor(props) { super(props); this.spread = null; } render() { return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}> </SpreadSheets> </div> <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" onClick={() => this.groupCallback()}/> <input type="button" value="Remove Group" id="removeGroupButton" onClick={() => this.removeGroupCallback()}/> </div> </div> </div> ); } initSpread(spread) { this.spread = 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(); } }
<!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/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/spread/source/data/orderDataSource.js" type="text/javascript"></script> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('$DEMOROOT$/en/lib/react/license.js').then(function () { System.import('./src/app'); }); </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% - 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: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js', '@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'react': 'npm:react/umd/react.production.min.js', 'react-dom': 'npm:react-dom/umd/react-dom.production.min.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' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);