Pivot Panel

The PivotPanel, shown on the right in the example below, lets you add, remove, drag, and rearrange fields in the pivot table. It consists of three sections—PivotTable Fields (including a search to quickly locate specific fields), PivotTable Area, and Pivot View Manager—and can be easily customized.

The PivotPanel consists of three sections Fields Section (Field Selection Area) Displays all available data source fields in a list Users can quickly add/remove fields to the pivot table via checkboxes Supports drag & drop fields to the areas below (Filters/Rows/Columns/Values) Search box can quickly filter the field list Area Section (Drag-and-Drop Zones) In the PivotTable Area Section, there are four areas: Filters: Controls the data range of the PivotTable. Columns: Controls the column distribution of the PivotTable. Rows: Controls the row distribution of the PivotTable. Values: Controls the summary data and the summary method of the PivotTable. ViewList Section (View Management) Manage multiple view configurations for the pivot table Quickly switch between different field layout configurations Add View: Save current field configuration as a new view Apply View: Restore a previously saved configuration Dropdown list displays all saved view names Auto Group Date Field When adding a date field to the Rows or Columns area, the PivotTable can automatically group it based on the date range of the data. The grouping granularity is determined automatically: Data spanning multiple years: Groups by Years, Quarters, Months Data spanning months within a single year: Groups by Months, Days Data spanning days within a single month: Groups by Days and time components To enable this feature, listen to the PivotTableChanging event and set autoGroupDateField to true: You can create the PivotPanel as follows: And user must set the width and height for the "panel" element. The params of the GC.Spread.Pivot.PivotPanel constructor are below: Param Type Description name string The name of pivot panel. pivotTable GC.Spread.Pivot.PivotTable The pivot panel relate to which pivot table. host HTMLDivElement Host pivot panel in this container. The PivotPanel is only a tool to control the PivotTable, and it will auto-dispose when using fromJSON. The PivotTable can work without a PivotPanel. PivotTable supports the below APIs to deal with the relationship between PivotPanel and PivotTable. Attaching a PivotPanel to the PivotTable: Detaching the PivotPanel from the PivotTable: Destroying the PivotPanel:
import * as React from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; import { AppFunc } from './app-func'; import { App } from './app-class'; // 1. Functional Component sample createRoot(document.getElementById('app')).render(<AppFunc />); // 2. Class Component sample // createRoot(document.getElementById('app')).render(<App />);
import * as React from 'react'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-shapes"; import "@mescius/spread-sheets-pivot-addon"; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; import './styles.css'; export function AppFunc() { let initSpread = function (spread) { initSheets(spread); let pivotLayoutSheet = spread.getSheet(0); initPivotTable(pivotLayoutSheet); initAutoGroupOption(pivotLayoutSheet); } let initSheets = function (spread) { spread.suspendPaint(); let sheet = spread.getSheet(1); sheet.name("DataSource"); sheet.setRowCount(117); sheet.setColumnWidth(0, 120); sheet.getCell(-1, 0).formatter("YYYY-mm-DD"); sheet.getRange(-1, 4, 0, 2).formatter("$ #,##0"); sheet.setArray(0, 0, pivotSales); let table = sheet.tables.add('tableSales', 0, 0, 117, 6); for (let i = 2; i <= 117; i++) { sheet.setFormula(i - 1, 5, '=D' + i + '*E' + i) } table.style(GC.Spread.Sheets.Tables.TableThemes["none"]); let sheet0 = spread.getSheet(0); sheet0.name("PivotLayout"); sheet0.setColumnCount(50); spread.resumePaint(); } let initPivotTable = function (sheet) { let myPivotTable = sheet.pivotTables.add("myPivotTable", "tableSales", 1, 1, GC.Spread.Pivot.PivotTableLayoutType.outline, GC.Spread.Pivot.PivotTableThemes.light8); myPivotTable.suspendLayout(); myPivotTable.options.showRowHeader = true; myPivotTable.options.showColumnHeader = true; myPivotTable.add("car", "Cars", GC.Spread.Pivot.PivotTableFieldType.columnField); myPivotTable.add("total", "Totals", GC.Spread.Pivot.PivotTableFieldType.valueField, GC.Pivot.SubtotalType.sum); let panel = new GC.Spread.Pivot.PivotPanel("myPivotPanel", myPivotTable, document.getElementById("panel")); panel.sectionVisibility(GC.Spread.Pivot.PivotPanelSection.fields + GC.Spread.Pivot.PivotPanelSection.area); myPivotTable.resumeLayout(); myPivotTable.autoFitColumn(); } let initAutoGroupOption = function (sheet) { let autoGroupEnabled = false; sheet.bind(GC.Spread.Sheets.Events.PivotTableChanging, function (sender, args) { if (autoGroupEnabled) { args.autoGroupDateField = true; } }); let checkbox = document.getElementById('autoGroupDate'); checkbox.addEventListener('change', function () { autoGroupEnabled = this.checked; }); } return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => initSpread(spread)}> <Worksheet> </Worksheet> <Worksheet> </Worksheet> </SpreadSheets> </div> <div class="sample-panel"> <div class="auto-group-option"> <input type="checkbox" id="autoGroupDate" /> <label htmlFor="autoGroupDate">Enable auto grouping when adding date fields</label> </div> <div id="panel"></div> </div> </div> ); }
import * as React from 'react'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-shapes"; import "@mescius/spread-sheets-pivot-addon"; import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react'; import './styles.css'; const Component = React.Component; export class App extends Component { render() { return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}> <Worksheet> </Worksheet> <Worksheet> </Worksheet> </SpreadSheets> </div> <div class="sample-panel"> <div class="auto-group-option"> <input type="checkbox" id="autoGroupDate" /> <label htmlFor="autoGroupDate">Enable auto grouping when adding date fields</label> </div> <div id="panel"></div> </div> </div> ); } initSpread(spread) { this.initSheets(spread); let pivotLayoutSheet = spread.getSheet(0); this.initPivotTable(pivotLayoutSheet); this.initAutoGroupOption(pivotLayoutSheet); } initSheets(spread) { spread.suspendPaint(); let sheet = spread.getSheet(1); sheet.name("DataSource"); sheet.setRowCount(117); sheet.setColumnWidth(0, 120); sheet.getCell(-1, 0).formatter("YYYY-mm-DD"); sheet.getRange(-1, 4, 0, 2).formatter("$ #,##0"); sheet.setArray(0, 0, pivotSales); let table = sheet.tables.add('tableSales', 0, 0, 117, 6); for (let i = 2; i <= 117; i++) { sheet.setFormula(i - 1, 5, '=D' + i + '*E' + i) } table.style(GC.Spread.Sheets.Tables.TableThemes["none"]); let sheet0 = spread.getSheet(0); sheet0.name("PivotLayout"); sheet0.setColumnCount(50); spread.resumePaint(); } initPivotTable(sheet) { let myPivotTable = sheet.pivotTables.add("myPivotTable", "tableSales", 1, 1, GC.Spread.Pivot.PivotTableLayoutType.outline, GC.Spread.Pivot.PivotTableThemes.light8); myPivotTable.suspendLayout(); myPivotTable.options.showRowHeader = true; myPivotTable.options.showColumnHeader = true; myPivotTable.add("car", "Cars", GC.Spread.Pivot.PivotTableFieldType.columnField); myPivotTable.add("total", "Totals", GC.Spread.Pivot.PivotTableFieldType.valueField, GC.Pivot.SubtotalType.sum); let panel = new GC.Spread.Pivot.PivotPanel("myPivotPanel", myPivotTable, document.getElementById("panel")); panel.sectionVisibility(GC.Spread.Pivot.PivotPanelSection.fields + GC.Spread.Pivot.PivotPanelSection.area); myPivotTable.resumeLayout(); myPivotTable.autoFitColumn(); } initAutoGroupOption(sheet) { let autoGroupEnabled = false; sheet.bind(GC.Spread.Sheets.Events.PivotTableChanging, function (sender, args) { if (autoGroupEnabled) { args.autoGroupDateField = true; } }); let checkbox = document.getElementById('autoGroupDate'); checkbox.addEventListener('change', function () { autoGroupEnabled = this.checked; }); } }
<!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/pivot-data.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"></div> </body> </html>
.sample-tutorial { position: relative; height: 100%; } .sample-spreadsheets { width: calc(100% - 300px); height: 100%; overflow: hidden; float: left; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow: hidden; } .sample-panel { float: right; width: 300px; height: 100%; box-sizing: border-box; background: #e6e6e6; overflow: hidden; } .gc-panel { padding: 10px; background-color: rgb(230, 230, 230); } .auto-group-option { padding: 10px 5px 10px 10px; font-size: 12px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; color: #333; display: flex; align-items: center; gap: 6px; } .auto-group-option input[type="checkbox"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; margin: 0; width: 14px; height: 14px; flex-shrink: 0; cursor: pointer; background: transparent; background-size: contain; background-repeat: no-repeat; background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTIiIHZpZXdCb3g9IjEgMSAxNCAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48dGl0bGU+Q2hlY2tib3gtVW5jaGVja2VkPC90aXRsZT48ZyBpZD0iQ2hlY2tib3gtVW5jaGVja2VkIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNMTMsMSBDMTQuMTA0NTY5NSwxIDE1LDEuODk1NDMwNSAxNSwzIEwxNSwxMyBDMTUsMTQuMTA0NTY5NSAxNC4xMDQ1Njk1LDE1IDEzLDE1IEwzLDE1IEMxLjg5NTQzMDUsMTUgMSwxNC4xMDQ1Njk1IDEsMTMgTDEsMyBDMSwxLjg5NTQzMDUgMS44OTU0MzA1LDEgMywxIEwxMywxIFogTTEzLDIuNSBMMywyLjUgQzIuNzIzODU3NjMsMi41IDIuNSwyLjcyMzg1NzYzIDIuNSwzIEwyLjUsMTMgQzIuNSwxMy4yNzYxNDI0IDIuNzIzODU3NjMsMTMuNSAzLDEzLjUgTDEzLDEzLjUgQzEzLjI3NjE0MjQsMTMuNSAxMy41LDEzLjI3NjE0MjQgMTMuNSwxMyBMMTMuNSwzIEMxMy41LDIuNzIzODU3NjMgMTMuMjc2MTQyNCwyLjUgMTMsMi41IFoiIGlkPSJjYiIgZmlsbD0iYmxhY2siPjwvcGF0aD48L2c+PC9zdmc+"); } .auto-group-option input[type="checkbox"]:checked { background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTIiIHZpZXdCb3g9IjEgMSAxNCAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48dGl0bGU+Q2hlY2tib3gtQ2hlY2tlZDwvdGl0bGU+PGcgaWQ9IkNoZWNrYm94LUNoZWNrZWQiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0xMywxIEMxNC4xMDQ1Njk1LDEgMTUsMS44OTU0MzA1IDE1LDMgTDE1LDEzIEMxNSwxNC4xMDQ1Njk1IDE0LjEwNDU2OTUsMTUgMTMsMTUgTDMsMTUgQzEuODk1NDMwNSwxNSAxLDE0LjEwNDU2OTUgMSwxMyBMMSwzIEMxLDEuODk1NDMwNSAxLjg5NTQzMDUsMSAzLDEgTDEzLDEgWiBNMTIuNTU0MzcwNiw0LjcxOTY2OTkxIEMxMi4yNjE0Nzc0LDQuNDI2Nzc2NyAxMS43ODY2MDM3LDQuNDI2Nzc2NyAxMS40OTM3MTA1LDQuNzE5NjY5OTEgTDYuNjg3NjYxMzcsOS41MjUgTDQuNDQwOTkxNDUsNy4yNzgzNDQ3OSBDNC4xNDgwOTgyMyw2Ljk4NTQ1MTU4IDMuNjczMjI0NSw2Ljk4NTQ1MTU4IDMuMzgwMzMxMjgsNy4yNzgzNDQ3OSBDMy4wODc0MzgwNiw3LjU3MTIzODAxIDMuMDg3NDM4MDYsOC4wNDYxMTE3NSAzLjM4MDMzMTI4LDguMzM5MDA0OTcgTDYuMTU3NjgzNDMsMTEuMTE2MzU3MSBDNi4yOTA4MTY3MSwxMS4yNDk0OTA0IDYuNDYxNTQ5MjcsMTEuMzIyMTA4NSA2LjYzNTY5OTk1LDExLjMzNDIxMTYgTDYuNzQwMzI3MDgsMTEuMzM0MjExNiBMNi44NDQxMzM4NiwxMS4zMTk2ODc5IEM2Ljk4MTI2NjgxLDExLjI5MDY0MDcgNy4xMTE4MzY5OCwxMS4yMjI4NjM3IDcuMjE4MzQzNiwxMS4xMTYzNTcxIEwxMi41NTQzNzA2LDUuNzgwMzMwMDkgQzEyLjg0NzI2MzgsNS40ODc0MzY4NyAxMi44NDcyNjM4LDUuMDEyNTYzMTMgMTIuNTU0MzcwNiw0LjcxOTY2OTkxIFoiIGlkPSJjYiIgZmlsbD0iYmxhY2siPjwvcGF0aD48L2c+PC9zdmc+"); } .auto-group-option label { cursor: pointer; user-select: none; } #panel { width: 300px; height: calc(100% - 36px); } #app { height: 100%; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/', 'cdn:': 'https://cdn.mescius.io/demoapps/packages/spreadjs/19.1.2-master-2026-06-10-2131/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'cdn:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-shapes': 'cdn:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-pivot-addon': 'cdn:@mescius/spread-sheets-pivot-addon/index.js', '@mescius/spread-sheets-react': 'cdn:@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/cjs/react.production.js', 'react-dom': 'npm:react-dom/cjs/react-dom.production.js', 'react-dom/client': 'npm:react-dom/cjs/react-dom-client.production.js', 'scheduler': 'npm:scheduler/cjs/scheduler.production.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);