Group Layout

TableSheet supports using a group layout, enabling you to define the header aggregations and footer subtotals.

Description
app.jsx
index.html
styles.css
Copy to CodeMine

Layout Mode

TableSheet supports three different Group Layouts, which can be set by groupLayout:

tableSheet.options.groupLayout = {
    mode: GC.Spread.Sheets.TableSheet.GroupLayoutMode.outline
};

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.

tableSheet.groupBy([
    {
        field: "priority",
        spacing: { row: 20 }
    }
]);

Multiple Group Fields

Multiple group headings can be added, with different levels of indentation for the content of the grouped items.

tableSheet.groupBy([
    {
        field: "priority"
    },
    {
        field: "duration"
    }
]);

Summary Fields Options

Users can set the content of each field.

tableSheet.groupBy([
    {
        field: "priority",
        summaryFields: [
            {  
                caption: "PRIORITY_FOOTER",
                formula: '="1st Summary Footer"',
                position: 'footer',
                relateTo: 'name',
                style: {
                    formatter: "$ #,##0.00",
                    backColor: 'green' 
                }
            },
        ]
    }
]);
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 * as React from 'react'; import * as ReactDOM from 'react-dom'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-tablesheet"; import { SpreadSheets } from '@mescius/spread-sheets-react'; import './styles.css'; export function AppFunc() { const [selectedTab, setSelectedTab] = React.useState(0); const [tableSheetGroupLayoutMode, setTableSheetGroupLayoutMode] = React.useState(1); const [tableSheetGroupLayoutPosition, setTableSheetGroupLayoutPosition] = React.useState("header"); const [sheet, setSheet] = React.useState(null); const 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" } } ] } ] const 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", } ] } ] let initSpread = function (spread) { 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); setSheet(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(OutlineAndCondensedGroup); }); spread.resumePaint(); initSplitView(spread); } const resetGroupLayout = function (mode, position) { sheet.options.groupLayout = { mode: mode, position: position }; if (mode === 0) { sheet.groupBy(TabularGroup); } else { sheet.groupBy(OutlineAndCondensedGroup); } } const handleTableSheetGroupLayoutMode = (event) => { setTableSheetGroupLayoutMode(+event.target.value); resetGroupLayout(+event.target.value, tableSheetGroupLayoutPosition); }; const handleTableSheetGroupLayoutPosition = (event) => { setTableSheetGroupLayoutPosition(event.target.value); resetGroupLayout(tableSheetGroupLayoutMode, event.target.value); }; return ( <div id="split-view" class="sample-tutorial"> <div class="sample-spreadsheets split-content"> <SpreadSheets workbookInitialized={spread => initSpread(spread)}> </SpreadSheets> </div> <div class="split-panel"> <div class="split-tabs"> <button key={1} className={`split-tab-link ${selectedTab === 0 ? 'active' : ''}`} onClick={() => setSelectedTab(0)}>TableSheet Panel</button> <button key={0} className={`split-tab-link ${selectedTab === 1 ? 'active' : ''}`} onClick={() => setSelectedTab(1)}>Setting</button> </div> <div class="split-panels"> <div id="panel" key={0} className={`split-tab-content ${selectedTab === 0 ? 'active' : ''}`}></div> <div id="settings" key={1} className={`split-tab-content ${selectedTab === 1 ? 'active' : ''}`}> <fieldset> <legend>Group Layout Mode</legend> <select id="tableSheetGroupLayoutMode" value={tableSheetGroupLayoutMode} onChange={handleTableSheetGroupLayoutMode}> <option value="0">Tabular</option> <option value="1">Outline</option> <option value="2">Condensed</option> </select> </fieldset> <fieldset> <legend>Default Summary Position</legend> <select id="tableSheetGroupLayoutPosition" value={tableSheetGroupLayoutPosition} onChange={handleTableSheetGroupLayoutPosition}> <option value="header" selected>Header</option> <option value="footer">Footer</option> </select> </fieldset> </div> </div> </div> </div> ); } function initSplitView(spread) { 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 }); } ReactDOM.render(<AppFunc />, document.getElementById('app'));
<!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"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/spread/source/splitView/splitView.css"> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.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> 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; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: 0; } .sample-spreadsheets { width: calc(100% - 303px); 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; height: 100%; } .split-tab-content.active { display: block; }
(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);