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:
<template>
<div class="sample-tutorial">
<gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread">
<gc-worksheet>
</gc-worksheet>
<gc-worksheet>
</gc-worksheet>
</gc-spread-sheets>
<div class="sample-panel">
<div class="auto-group-option">
<input type="checkbox" id="autoGroupDate" @change="onAutoGroupChange">
<label for="autoGroupDate">Enable auto grouping when adding date fields</label>
</div>
<div id="panel"></div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import GC from "@mescius/spread-sheets";
import "@mescius/spread-sheets-shapes";
import "@mescius/spread-sheets-vue";
import "@mescius/spread-sheets-pivot-addon";
let autoGroupEnabled = ref(false);
function onAutoGroupChange(e) {
autoGroupEnabled.value = e.target.checked;
}
async function initSpread(spread) {
initSheets(spread);
let pivotLayoutSheet = spread.getSheet(0);
initPivotTable(pivotLayoutSheet);
pivotLayoutSheet.bind(GC.Spread.Sheets.Events.PivotTableChanging, function (sender, args) {
if (autoGroupEnabled.value) {
args.autoGroupDateField = true;
}
});
}
function 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();
}
function 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();
}
</script>
<style scoped>
.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%;
}
</style>
<!DOCTYPE html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>SpreadJS VUE</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css"
href="$DEMOROOT$/en/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<script src="$DEMOROOT$/spread/source/data/pivot-data.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/vue3/node_modules/systemjs/dist/system.src.js"></script>
<script src="./systemjs.config.js"></script>
<script src="./compiler.js" type="module"></script>
<script>
var System = SystemJS;
System.import("./src/app.js");
System.import('$DEMOROOT$/en/lib/vue3/license.js');
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
(function (global) {
SystemJS.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true
},
paths: {
// paths serve as alias
'npm:': 'node_modules/',
'cdn:': 'https://cdn.mescius.io/demoapps/packages/spreadjs/19.1.2-master-2026-06-10-2131/'
},
packageConfigPaths: [
'../node_modules/*/package.json',
"../node_modules/@mescius/*/package.json",
"../node_modules/@babel/*/package.json",
"../node_modules/@vue/*/package.json"
],
map: {
'vue': "npm:vue/dist/vue.esm-browser.js",
'tiny-emitter': 'npm:tiny-emitter/index.js',
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
"systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js",
'@mescius/spread-sheets': 'cdn:@mescius/spread-sheets/index.js',
'@mescius/spread-sheets-resources-en': 'cdn:@mescius/spread-sheets-resources-en/index.js',
'@mescius/spread-sheets-vue': 'cdn:@mescius/spread-sheets-vue/index.js',
'@mescius/spread-sheets-pivot-addon': 'cdn:@mescius/spread-sheets-pivot-addon/index.js',
'@mescius/spread-sheets-shapes': 'cdn:@mescius/spread-sheets-shapes/index.js'
},
meta: {
'*.css': { loader: 'systemjs-plugin-css' },
'*.vue': { loader: "../plugin-vue/index.js" }
}
});
})(this);