logo

S2

  • Manual
  • API
  • Examples
  • Playground
  • ChangeLog
  • Productsantv logo arrow
  • 2.x
  • Introduction
  • Quick Start
  • Basic Tutorial
    • Base Concept
    • Sheet Type
      • Pivot Mode
        Updated
      • Table Mode
    • Conditions
      Updated
    • Totals
    • Sort
      • Custom Sort
        Updated
      • Group Sort
        Updated
    • Theme
      Updated
    • Tooltip
      Updated
    • Internationalization
    • 数据格式化
      New
    • Multi Line
      New
    • Pagination
      New
  • Advanced Tutorial
    • Advanced Tutorial
      • Link
      • Render Chart In Cell
      • Draw Chart With @antv/g2
    • Custom
      • Customize Hook
        Updated
      • Customize Tree
        New
      • Customize Icon
      • Customize Cell Alignment
      • Customize Cell Size
        Updated
      • Customize Order
      • Custom Collapse/Expand Nodes
    • Interaction
      • Basic Interaction
      • Custom Interaction
      • Hide Columns
      • Cell Resize
      • Merge Cell
      • Scroll
      • Copy
        New
      • Highlight and select cell
        New
    • Analyze Component
      • Introduction
        New
      • Advanced Sort
        Updated
      • Switcher
      • Export
        Updated
      • Pagination
      • Drill Down
    • Sheet Component
      • Editable Mode
      • Strategy Sheet
        Updated
    • HD Adapter
    • Get Instance
    • Get Cell Data
      Updated
    • Table adaptive
    • AntV/G Plugins
      New
    • Pivot Chart
      Experimental
    • Vue 3.0
  • Extended Reading
    • Data Process
      • Pivot
      • Table
    • Layout
      • Pivot
      • Table
    • Performance
      Updated
  • Contribution
  • FAQ
  • S2 2.0 Migration Guide

Pivot

Previous
Vue 3.0
Next
Table

Resources

Ant Design
Galacea Effects
Umi-React Application Framework
Dumi-Component doc generator
ahooks-React Hooks Library

Community

Ant Financial Experience Tech
seeconfSEE Conf-Experience Tech Conference

Help

GitHub
StackOverflow

more productsMore Productions

Ant DesignAnt Design-Enterprise UI design language
yuqueYuque-Knowledge creation and Sharing tool
EggEgg-Enterprise-class Node development framework
kitchenKitchen-Sketch Tool set
GalaceanGalacean-互动图形解决方案
xtechLiven Experience technology
© Copyright 2025 Ant Group Co., Ltd..备案号:京ICP备15032932号-38

Loading...

This article will introduce the data flow processing process of the pivot table, so that readers can understand the internal data logic of S2 more intuitively.

The data processing process is:原始数据-> 生成多维数组-> 生成层级结构-> 获取数据, and we will explain them one by one, the goal is to realize the pivot table in the following figure:

s2-data-process-demo

Raw data

The initial configuration and data are as follows:

const dataCfg = {
fields: {
rows: ['province', 'city'],
columns: ['type', 'sub_type'],
values: ['price']
},
data: [{
"price": 1,
"province": "浙江省",
"city": "杭州市",
"type": "家具",
"sub_type": "桌子"
}, {
"price": 2,
"province": "浙江省",
"city": "绍兴市",
"type": "家具",
"sub_type": "桌子"
}, {
"price": 3,
"province": "浙江省",
"city": "杭州市",
"type": "家具",
"sub_type": "沙发"
}, {
"price": 4,
"province": "浙江省",
"city": "绍兴市",
"type": "家具",
"sub_type": "沙发"
}]
};
const options = {
width: 600,
height: 600
};
<SheetComponent
dataCfg={dataCfg}
options={options}
sheetType="pivot"
/>

generate multidimensional array

First, process the third piece of data to extract the row and column dimension results of the current detailed data under the initial configuration conditions.

// 第四条数据
// { "price": 4,"province": "浙江省","city": "绍兴市","type": "家具","sub_type": "沙发" }
const rowDimensionValues = transformDimensionsValue(currentData, ['province', 'city']); // 结果是 ['浙江省', '绍兴市']
const colDimensionValues = transformDimensionsValue(currentData, ['type', 'sub_type']); // 结果是 ['家具', '沙发']

Then, according to the row and column dimension results of the data and the initial configuration conditions, we can obtain the path to the current detailed data (that is, the coordinate index in the row tree structure and column tree structure)

const rowPath = getPath(rowDimensionValues); // 结果是 [0, 1]; 因为浙江下面有杭州和绍兴,所以绍兴坐标为 1,下同。
const colPath = getPath(colDimensionValues); // 结果是 [0, 1];
const dataPath = rowPath.concat(...colPath); // 结果是 [0, 1, 0, 1];
lodash.set(indexesData, dataPath, currentData); // [0, 1, 0, 1] 是 { "price": 4,"province": "浙江省","city": "绍兴市","type": "家具","sub_type": "沙发" }

Finally, according to the above process, traverse all the data to get the final multidimensional array, the result is:

[
[
[
[
[{
"price": 1,
"province": "浙江省",
"city": "杭州市",
"type": "家具",
"sub_type": "桌子",
"$$extra$$": "price",
"$$value$$": 1
}],
[{
"price": 3,
"province": "浙江省",
"city": "杭州市",
"type": "家具",
"sub_type": "沙发",
"$$extra$$": "price",
"$$value$$": 3
}]
]
],
[
[
[{
"price": 2,
"province": "浙江省",
"city": "绍兴市",
"type": "家具",
"sub_type": "桌子",
"$$extra$$": "price",
"$$value$$": 2
}],
[{
"price": 4,
"province": "浙江省",
"city": "绍兴市",
"type": "家具",
"sub_type": "沙发",
"$$extra$$": "price",
"$$value$$": 4
}]
]
]
]
]

generate hierarchy

The next step is to generate a tree structure of rows and columns according to the data structure. We know that there are generally three meta structures for storing detailed data: flat arrays, graphs, and trees. The query frequency for table scenarios is very high, and the presentation form of the pivot table itself also expresses a tree structure, so we chose to build a tree structure Structure to implement Meta.

Next, we take the row tree structure as an example to explain the construction process of the hierarchical structure in S2 .

First, get the row dimension enumeration value of a piece of data:

// 第四条数据
// { "price": 4,"province": "浙江省","city": "绍兴市","type": "家具","sub_type": "沙发" }
const rowDimensionValues = transformDimensionsValue(currentData, ['province', 'city']); // 结果是 ['浙江省', '绍兴市']

Then, traverse the row dimension enumeration of this piece of data:

let currentMeta = this.rowPivotMeta; // 存储行树形结构 Map.
for (let i = 0; i < rowDimensionValues.length; i++) { // 遍历 ['浙江省', '绍兴市'];
if (isFirstCreate) {
currentMeta.set(rowDimensionValues[i], { // currentMeta =
level: currentMeta.size,
children: new Map(),
});
}
const meta = this.rowPivotMeta.get(value);
currentMeta = meta?.children;
}

When looping ['浙江省', '绍兴市'] for the first time, the result of currentMeta is:

Map(1) {
[[entries]] => [{
'浙江省' => { key: '浙江省', value: { children: Map(0)}})
}]
}

The result of the second loop is:

Map(1) {
[[Entries]] => [{
'浙江省' => { key: '浙江省', value: {
children: Map(1) {
[[Entries]] => [{
'绍兴市' => { key: '绍兴市', value: { children: Map(0)}}
}]
}
}}
}]
}

After traversing a piece of detailed data, it becomes a hierarchical structure such as浙江省=> 绍兴市. After traversing all the detailed data, the final row hierarchy is as follows:

Map(1) {
[[Entries]] => [{
'浙江省' => { key: '浙江省', value: {
childField: 'city',
children: Map(2) {
[[Entries]] => [{
'杭州市' => { key: '杭州市', value: { children: Map(0)}}
}, {
'绍兴市' => { key: '绍兴市', value: { children: Map(0)}}
}]
}
}}
}]
}

The final hierarchy of columns is as follows:

Map(1) {
[[Entries]] => [{
'家具' => { key: '家具', value: {
childField: 'sub_type',
children: Map(2) {
[[Entries]] => [{
'桌子' => { key: '桌子', value: { children: Map(0)}}
}, {
'沙发' => { key: '沙发', value: { children: Map(0)}}
}]
}
}}
}]
}

retrieve data

When rendering a pivot table data cell, it is necessary to obtain the corresponding display content (data). For example, when the cell data in the lower right corner is needed, the code is as follows:

const data = getCellData({
query: { province: '浙江省', city: '绍兴市', type: '家具', sub_type: '沙发', $$extra$$: 'price' }
});

The implementation process is to first get the row and column dimension enumeration values:

const rowDimensionValues = getQueryDimValues(['province', 'city'], query); // ['浙江省', '绍兴市']
const colDimensionValues = getQueryDimValues(['type', 'sub_type', '$$extra$$'], query); // ['家具', '沙发', 'price']

Then obtain the data query path through the enumeration value, and get the specific data from the multidimensional array generated earlier.

const path = getDataPath({ rowDimensionValues, colDimensionValues }); // [0, 1, 0, 1, 0]
const data = lodash.get(indexesData, path);

To sum up, to obtain data is to construct the data path corresponding to the current query condition through the query condition, and then directly fetch it from the multidimensional array.