Skip to content

Commit 7fa5191

Browse files
authored
Merge pull request #4921 from VisActor/4850-feature-showSubTotalsOnTreeNode
4850 feature show sub totals on tree node
2 parents 5a1ae61 + d1a5639 commit 7fa5191

File tree

6 files changed

+75
-36
lines changed

6 files changed

+75
-36
lines changed

docs/assets/guide/en/data_analysis/pivot_table_dataAnalysis.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,16 @@ dataConfig: {
8484
subTotalsDimensions: ['province'],
8585
grandTotalLabel: 'row total',
8686
subTotalLabel: 'Subtotal',
87-
showGrandTotalsOnTop: true //totals show on top
87+
showGrandTotalsOnTop: true, //totals show on top
88+
showSubTotalsOnTreeNode: false // When subtotals are disabled in pivot tables, this option allows aggregated values to be displayed on collapsed tree nodes. Default value is false.
8889
},
8990
column: {
9091
showGrandTotals: true,
9192
showSubTotals: true,
9293
subTotalsDimensions: ['quarter'],
9394
grandTotalLabel: 'column total',
94-
subTotalLabel: 'Subtotal'
95+
subTotalLabel: 'Subtotal',
96+
showSubTotalsOnTreeNode: false // When subtotals are disabled in pivot tables, this option allows aggregated values to be displayed on collapsed tree nodes. Default value is false.
9597
}
9698
}
9799
},
@@ -250,9 +252,10 @@ dataConfig:{
250252
}]
251253
}
252254
```
253-
In this data record, the sales indicator is a non-numeric value. If the product requirement is to directly display `"NULL"` in the table cell, then the aggregation rule can be set to `VTable.TYPES.AggregationType.NONE`, so that VTable's internal will not perform aggregation calculations, but directly take the `sales` field value as the display value of the cell.
254255

255-
2. AggregationType.RECORD usage scenario is mainly used to match all data based on the user's input data record and use it as the display data of the cell. Usage scenarios include: needing to collect data sets for mini-chart displays, specific demo see: https://visactor.io/vtable/demo/cell-type/pivot-sparkline
256+
In this data record, the sales indicator is a non-numeric value. If the product requirement is to directly display `"NULL"` in the table cell, then the aggregation rule can be set to `VTable.TYPES.AggregationType.NONE`, so that VTable's internal will not perform aggregation calculations, but directly take the `sales` field value as the display value of the cell.
257+
258+
2. AggregationType.RECORD usage scenario is mainly used to match all data based on the user's input data record and use it as the display data of the cell. Usage scenarios include: needing to collect data sets for mini-chart displays, specific demo see: https://visactor.io/vtable/demo/cell-type/pivot-sparkline
256259

257260
#### Custom Aggregation Type Introduction
258261

@@ -313,7 +316,7 @@ const option={
313316
{
314317
indicatorKey: 'Average Product Price (Registered Aggregation Class)', //Indicator name
315318
field: 'sales', //Indicator based field
316-
aggregationType: 'avgPrice', //Registered aggregation type
319+
aggregationType: 'avgPrice', //Registered aggregation type
317320
}
318321
]
319322
}
@@ -323,6 +326,7 @@ const option={
323326
VTable's internal aggregation rules code address: https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/ts-types/dataset/aggregation.ts, can be referred to!
324327

325328
The methods that need to be implemented for the aggregation type are:
329+
326330
- constructor: The constructor function, used to initialize the aggregator.
327331
- push: Add data records to the aggregator, used to calculate the aggregated value.
328332
- deleteRecord: Delete records from the aggregator and update the aggregated value, called by VTable's delete interface deleteRecords.
@@ -591,4 +595,4 @@ Interface definition:
591595
* @param isResetTree Whether to reset the table header tree structure. When true, the table header tree structure will be reset, when false, the table header tree structure will remain unchanged
592596
*/
593597
updateFilterRules(filterRules: FilterRules, isResetTree: boolean = false) => void
594-
```
598+
```

docs/assets/guide/zh/data_analysis/pivot_table_dataAnalysis.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,16 @@ dataConfig: {
8484
subTotalsDimensions: ['province'],
8585
grandTotalLabel: '行总计',
8686
subTotalLabel: '小计',
87-
showGrandTotalsOnTop: true //汇总值显示在上
87+
showGrandTotalsOnTop: true, //汇总值显示在上
88+
showSubTotalsOnTreeNode: false // 当在透视表中禁用小计时,此选项允许在折叠的树节点上显示聚合值。默认值为 false
8889
},
8990
column: {
9091
showGrandTotals: true,
9192
showSubTotals: true,
9293
subTotalsDimensions: ['quarter'],
9394
grandTotalLabel: '列总计',
94-
subTotalLabel: '小计'
95+
subTotalLabel: '小计',
96+
showSubTotalsOnTreeNode: false // 当在透视表中禁用小计时,此选项允许在折叠的树节点上显示聚合值。默认值为 false
9597
}
9698
}
9799
},
@@ -163,7 +165,7 @@ dataConfig: {
163165

164166
通常情况下指标应该是 `number` 类型,这样内部才能进行计算。
165167

166-
如果指标是字符串型或者 `null`,且需要在单元格中进行展示,可以配置 `aggregationType``VTable.TYPES.AggregationType.NONE` 来显示数据源字段的原始值; 或者在指标format函数中结合接口`getCellOriginRecord`获取到单元格对应的数据源条目,然后进行特殊处理。
168+
如果指标是字符串型或者 `null`,且需要在单元格中进行展示,可以配置 `aggregationType``VTable.TYPES.AggregationType.NONE` 来显示数据源字段的原始值; 或者在指标 format 函数中结合接口`getCellOriginRecord`获取到单元格对应的数据源条目,然后进行特殊处理。
167169

168170
如果用到了自定义渲染 `customLayout`,在 `customLayout` 函数中想获取单元格对应的所有数据 `records`,可以配置 `aggregationType``VTable.TYPES.AggregationType.RECORD`
169171

@@ -218,7 +220,7 @@ dataConfig: {
218220
{
219221
indicatorKey: '商品均价(注册聚合类)', //指标名称
220222
field: 'sales', //指标依据字段
221-
aggregationType: 'avgPrice', //自己注册的聚合类型
223+
aggregationType: 'avgPrice', //自己注册的聚合类型
222224
}
223225
]
224226
}
@@ -252,7 +254,7 @@ dataConfig:{
252254
}
253255
```
254256

255-
其中该条数据 record 中 sales 指标是个非数值型的值,如果产品需求要将`"NULL"`直接显示到表格单元格中,那么可以设置聚合规则为`VTable.TYPES.AggregationType.NONE`,这样 VTable 的内部不会进行聚合计算,而是直接取`sales`字段值作为单元格展示值。
257+
其中该条数据 record 中 sales 指标是个非数值型的值,如果产品需求要将`"NULL"`直接显示到表格单元格中,那么可以设置聚合规则为`VTable.TYPES.AggregationType.NONE`,这样 VTable 的内部不会进行聚合计算,而是直接取`sales`字段值作为单元格展示值。
256258

257259
2. AggregationType.RECORD 使用场景主要用于根据用户传入数据 record 匹配到所有数据,将其作为单元格的展示数据,用法场景如:需要搜集数据集作为迷你图展示,具体 demo 见:https://visactor.io/vtable/demo/cell-type/pivot-sparkline
258260

@@ -315,20 +317,21 @@ const option={
315317
{
316318
indicatorKey: '商品均价(注册聚合类)', //指标名称
317319
field: 'sales', //指标依据字段
318-
aggregationType: 'avgPrice', //自己注册的聚合类型
320+
aggregationType: 'avgPrice', //自己注册的聚合类型
319321
}
320322
]
321323
}
322324
}
323325
```
324326

325-
VTable内部的几种聚合规则代码地址https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/ts-types/dataset/aggregation.ts,可予以参考!
327+
VTable 内部的几种聚合规则代码地址https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/ts-types/dataset/aggregation.ts,可予以参考!
326328

327329
其中聚合类型需要实现的几个方法分别为:
330+
328331
- constructor:构造函数,用于初始化聚合器。
329332
- push:将数据记录添加到聚合器中,用于计算聚合值。
330-
- deleteRecord:从聚合器中删除记录,并更新聚合值,调用vtable的删除接口deleteRecords会调用该接口
331-
- updateRecord:更新数据记录,并更新聚合值,调用接口updateRecords会调用该接口
333+
- deleteRecord:从聚合器中删除记录,并更新聚合值,调用 vtable 的删除接口 deleteRecords 会调用该接口
334+
- updateRecord:更新数据记录,并更新聚合值,调用接口 updateRecords 会调用该接口
332335
- recalculate:重新计算聚合值,目前复制粘贴单元格值会调用该方法。
333336
- value:获取聚合值。
334337
- reset:重置聚合器。
@@ -593,4 +596,4 @@ VTable 官网示例:https://visactor.io/vtable/demo/table-type/pivot-table.
593596
* @param isResetTree 是否重置表头树结构。 当为true时,会重置表头树结构,当为false时,表头树结构维持不变
594597
*/
595598
updateFilterRules(filterRules: FilterRules, isResetTree: boolean = false) => void
596-
```
599+
```

docs/assets/option/en/table/pivotTable.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ export interface Total {
229229
grandTotalLabel?: string;
230230
//Default 'Subtotal'
231231
subTotalLabel?: string;
232+
// When subtotals are disabled in pivot tables, this option allows aggregated values to be displayed on collapsed tree nodes. Default value is false.
233+
showSubTotalsOnTreeNode?: boolean;
232234
}
233235
```
234236

@@ -268,6 +270,7 @@ export interface CalculatedFieldRule {
268270
calculateFun?: (dependFieldsValue: any) => any;
269271
}
270272
```
273+
271274
### updateAggregationOnEditCell (boolean)
272275

273276
Whether to update total and subtotal after editing cell value. Default value is false.
@@ -460,4 +463,5 @@ columnWidthConfigForRowHeader": [
460463
}
461464
]
462465
```
463-
Matching key is the key of the row dimension: dimensionKey。
466+
467+
Matching key is the key of the row dimension: dimensionKey。

docs/assets/option/zh/table/pivotTable.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ export interface Total {
233233
grandTotalLabel?: string;
234234
// 默认'小计'
235235
subTotalLabel?: string;
236+
// 当在透视表中禁用小计时,此选项允许在折叠的树节点上显示聚合值。默认值为 false
237+
showSubTotalsOnTreeNode?: boolean;
236238
}
237239
```
238240

@@ -272,9 +274,10 @@ export interface CalculateddFieldRule {
272274
calculateFun?: (dependFieldsValue: any) => any;
273275
}
274276
```
277+
275278
### updateAggregationOnEditCell (boolean)
276279

277-
是否在修改单元格后更新小计和总计。默认值为false.
280+
是否在修改单元格后更新小计和总计。默认值为 false.
278281

279282
具体情况请参考[demo](../demo/data-analysis/pivot-analysis-updateTotalData)
280283

@@ -450,6 +453,7 @@ export interface IIndicatorHeaderNode {
450453
## columnWidthConfigForRowHeader(Array)
451454

452455
依据行维度信息设置行表头列宽, 设置示例:
456+
453457
```
454458
columnWidthConfigForRowHeader": [
455459
{
@@ -463,5 +467,5 @@ columnWidthConfigForRowHeader": [
463467
}
464468
]
465469
```
466-
匹配关键是行维度的key:dimensionKey。
467470

471+
匹配关键是行维度的 key:dimensionKey。

packages/vtable/src/dataset/dataset.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,10 +1179,13 @@ export class Dataset {
11791179
// 如果是平铺树结构 小计需要处理补充到rowKey中
11801180
if (rowKey[0] === this.rowGrandTotalLabel) {
11811181
} else if (
1182-
this.totals?.row?.subTotalsDimensions &&
1183-
this.totals?.row?.subTotalsDimensions?.length >= 1 &&
1184-
rowKey[rowKey.length - 1] !== this.rowSubTotalLabel &&
1185-
this.totals.row.subTotalsDimensions.find((dimension: string) => dimension === rowDimensionKey) //如果维度key在subTotalsDimensions中 则需要补充小计标签名到rowKey中
1182+
(
1183+
(this.totals?.row?.subTotalsDimensions &&
1184+
this.totals?.row?.subTotalsDimensions?.length >= 1 &&
1185+
this.totals.row.subTotalsDimensions.find((dimension: string) => dimension === rowDimensionKey)) ||
1186+
this.totals?.row?.showSubTotalsOnTreeNode
1187+
) &&
1188+
rowKey[rowKey.length - 1] !== this.rowSubTotalLabel
11861189
) {
11871190
rowKey.push(this.rowSubTotalLabel);
11881191
}
@@ -1205,10 +1208,11 @@ export class Dataset {
12051208
if (colKey.length < this.columns.length && this.columnHierarchyType === 'grid-tree') {
12061209
if (colKey[0] === this.colGrandTotalLabel) {
12071210
} else if (
1208-
this.totals?.column?.subTotalsDimensions &&
1209-
this.totals?.column?.subTotalsDimensions?.length >= 1 &&
1210-
colKey[colKey.length - 1] !== this.colSubTotalLabel &&
1211-
this.totals.column.subTotalsDimensions.find((dimension: string) => dimension === colDimensionKey) //如果维度key在subTotalsDimensions中 则需要补充小计标签名到colKey中
1211+
((this.totals?.column?.subTotalsDimensions &&
1212+
this.totals?.column?.subTotalsDimensions?.length >= 1 &&
1213+
this.totals.column.subTotalsDimensions.find((dimension: string) => dimension === colDimensionKey)) ||
1214+
this.totals?.column?.showSubTotalsOnTreeNode) &&
1215+
colKey[colKey.length - 1] !== this.colSubTotalLabel
12121216
) {
12131217
colKey.push(this.colSubTotalLabel);
12141218
}
@@ -1542,12 +1546,20 @@ export class Dataset {
15421546
}
15431547
const colKey = flatColKey.split(this.stringJoinChar);
15441548
if (
1545-
that.totals?.column?.subTotalsDimensions &&
1549+
(that.totals?.column?.subTotalsDimensions &&
15461550
that.totals?.column?.subTotalsDimensions?.length > 0 &&
1547-
that.totals.column.showSubTotals !== false
1551+
(that.totals.column.showSubTotals !== false || that.totals.column.showSubTotalsOnTreeNode)) ||
1552+
(that.totals.column.showSubTotalsOnTreeNode && that.columns.length > 0)
15481553
) {
1549-
for (let i = 0, len = that.totals?.column?.subTotalsDimensions?.length; i < len; i++) {
1550-
const dimension = that.totals.column.subTotalsDimensions[i];
1554+
// 确定要处理的列维度
1555+
let colSubTotalDimensions = that.totals?.column?.subTotalsDimensions || [];
1556+
if (that.totals?.column?.showSubTotalsOnTreeNode && colSubTotalDimensions.length === 0) {
1557+
// 如果设置了showSubTotalsOnTreeNode但没有配置subTotalsDimensions,则使用所有列维度
1558+
colSubTotalDimensions = that.columns.map(col => col);
1559+
}
1560+
1561+
for (let i = 0, len = colSubTotalDimensions.length; i < len; i++) {
1562+
const dimension = colSubTotalDimensions[i];
15511563
const dimensionIndex = that.columns.indexOf(dimension);
15521564
if (dimensionIndex >= 0) {
15531565
const colTotalKey = colKey.slice(0, dimensionIndex + 1);
@@ -1687,7 +1699,9 @@ export class Dataset {
16871699
(that?.totals?.column?.subTotalsDimensions && that?.totals?.column?.subTotalsDimensions?.length >= 1) ||
16881700
(that?.totals?.row?.subTotalsDimensions && that?.totals?.row?.subTotalsDimensions?.length >= 1) ||
16891701
that?.totals?.column?.showGrandTotals ||
1690-
that?.totals?.row?.showGrandTotals
1702+
that?.totals?.row?.showGrandTotals ||
1703+
that?.totals?.row?.showSubTotalsOnTreeNode ||
1704+
that?.totals?.column?.showSubTotalsOnTreeNode
16911705
// ||
16921706
// that.rows.length === 0 || //todo 这里原有逻辑暂时注释掉
16931707
// that.columns.length === 0
@@ -1698,12 +1712,20 @@ export class Dataset {
16981712
const rowKey = flatRowKey.split(this.stringJoinChar);
16991713
Object.keys(that.tree[flatRowKey]).forEach(flatColKey => {
17001714
if (
1701-
that.totals?.row?.subTotalsDimensions &&
1715+
(that.totals?.row?.subTotalsDimensions &&
17021716
that.totals?.row?.subTotalsDimensions?.length > 0 &&
1703-
that.totals.row.showSubTotals !== false
1717+
(that.totals.row.showSubTotals !== false || that.totals.row.showSubTotalsOnTreeNode)) ||
1718+
(that.totals.row.showSubTotalsOnTreeNode && that.rows.length > 0)
17041719
) {
1705-
for (let i = 0, len = that.totals?.row?.subTotalsDimensions?.length; i < len; i++) {
1706-
const dimension = that.totals.row.subTotalsDimensions[i];
1720+
// 确定要处理的行维度
1721+
let rowSubTotalDimensions = that.totals?.row?.subTotalsDimensions || [];
1722+
if (that.totals?.row?.showSubTotalsOnTreeNode && rowSubTotalDimensions.length === 0) {
1723+
// 如果设置了showSubTotalsOnTreeNode但没有配置subTotalsDimensions,则使用所有行维度
1724+
rowSubTotalDimensions = that.rows.map(row => row);
1725+
}
1726+
1727+
for (let i = 0, len = rowSubTotalDimensions.length; i < len; i++) {
1728+
const dimension = rowSubTotalDimensions[i];
17071729
const dimensionIndex = that.rows.indexOf(dimension);
17081730
if (dimensionIndex >= 0 && dimensionIndex < that.rows.length - 1) {
17091731
const rowTotalKey = rowKey.slice(0, dimensionIndex + 1);

packages/vtable/src/ts-types/new-data-set.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export interface Total {
3939
showGrandTotals: boolean;
4040
/** 是否显示小计; 如果配置了total对象,showSubTotals默认为true */
4141
showSubTotals: boolean;
42+
/** 是否在树节点上显示聚合数据; 不需要开启showSubTotals小计就能折叠后显示聚合数据 */
43+
showSubTotalsOnTreeNode?: boolean;
4244

4345
// // 计算总计方法
4446
// calcGrandTotals?: CalcTotals;

0 commit comments

Comments
 (0)