概述
本 Demo 展示了集算表(TableSheet)的数据分组功能,按"发货地区"和"发货城市"两个字段进行二级分组,并为每个分组自动计算订单数量、运费总计等汇总信息。Demo 中使用了 outline 布局模式,以层次化的方式展示分组数据。
实现思路
创建集算表,从远程 API 加载订单数据
使用 DataManager 创建数据表和视图
调用 groupBy 方法设置分组配置,包括分组字段、标题样式和汇总字段
设置 groupLayout.mode 为 outline 布局模式
将集算表注册到普通工作表的 dataRange 中显示
调整行高和列宽,优化显示效果
代码解析
设置分组布局模式
这行代码设置分组布局模式。mode 可以取值为:0(tabular 表格模式)、1(condensed 紧凑模式)、2(outline 大纲模式)。Demo 中使用 outline 模式,以缩进和层次结构展示分组。
配置分组规则
groupBy 方法接受一个配置数组,每个配置对象代表一个分组级别:
field:分组依据的字段名
caption:分组标题
style:分组行的样式
summaryFields:汇总字段配置数组,每个汇总字段包含:
caption:汇总项标题
formula:计算公式,使用字段名引用数据(如 [Id])
relateTo:关联的字段(可选)
将集算表注册到工作表
dataRanges.add 方法将集算表注册到普通工作表中显示:
第一个参数:dataRange 的名称
第二个参数:集算表的名称
第三个参数:在工作表中显示的区域范围(-1 表示自动扩展)
运行效果
数据按"发货地区"分组,每个地区下又按"发货城市"进行二级分组
每个分组显示汇总信息,包括订单数量、运费总计等
分组以层次化的 outline 布局展示,分组标题有特殊的背景色和字号样式
用户可以展开或折叠各个分组,查看详细数据或汇总信息
API 参考
groupBy 方法
groupInfo:分组配置数组,每个元素包含:
field:分组字段名
caption:分组标题
style:分组行样式
summaryFields:汇总字段配置
dataRanges.add 方法
name:dataRange 名称
source:数据源名称(集算表名称)
range:显示区域范围
/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
window.onload = function() {
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 1 });
initSpread(spread);
};
function initSpread(spread) {
spread.suspendPaint();
var sheet = spread.getActiveSheet();
initTableSheet(spread, function(tableSheet) {
spread.setActiveSheet(sheet.name());
var dataRange = registerTableSheetIntoWorksheet(tableSheet, sheet);
beautifySheet(sheet, dataRange);
spread.undoManager().clear();
});
spread.resumePaint();
}
async function initTableSheet(spread, callback) {
spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader;
//init a data manager
var dataManager = spread.dataManager();
var orderAPI = getBaseApiUrl() + "/Order";
var orderTable = dataManager.addTable("orderTable", {
remote: {
read: {
url: orderAPI
}
}
});
//init a table sheet
var tableSheet = spread.addSheetTab(0, "MyTableSheet", GC.Spread.Sheets.SheetType.tableSheet);
await orderTable.fetch();
var myView = orderTable.addView("myView", [
{ value: "Id", width: 180, style: { formatter: "O00000" } },
{ value: "CustomerId", width: 200 },
{ value: "Freight", width: 150 },
{ value: "OrderDate", width: 100 },
{ value: "ShipRegion", width: 100 },
{ value: "ShipCity", width: 100 },
{ value: "ShipVia", width: 150 }
]);
tableSheet.setDataView(myView);
tableSheet.options.groupLayout.mode = 2;
tableSheet.groupBy([
{
field: "ShipRegion",
caption: "SHIP REGION",
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([Id])",
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 SHIP VIA",
formula: '=SUM([ShipVia])',
relateTo: "ShipVia",
style: { formatter: "$ #,##0.00", cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
},
{
caption: "Σ(Freight)",
formula: "=SUM([Freight])",
style: { cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
},
]
},
{
field: "ShipCity",
spacing: { row: 20 },
caption: "SHIP CITY",
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 SHIP VIA",
formula: '=SUM([ShipVia])',
position: "footer",
relateTo: "ShipVia",
style: { formatter: "$ #,##0.00", cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
},
{
caption: "SUBTOTAL FREIGHT",
formula: "=SUM([Freight])",
position: "footer",
style: { cellPadding: "30 0 0 0" },
headerStyle: { cellPadding: "8 0 0 0" }
}
]
}
]);
spread.suspendPaint();
callback && callback(tableSheet);
spread.resumePaint();
return tableSheet;
}
function registerTableSheetIntoWorksheet (tableSheet, sheet) {
var name = tableSheet.name() + "_DataRange";
var row = 1;
var col = 1;
var dataRange = sheet.dataRanges.add(name, tableSheet.name(), new GC.Spread.Sheets.Range(row, col, -1, -1));
return dataRange;
}
function beautifySheet(sheet, dataRange) {
var range = dataRange.range();
for (var i = range.row; i < range.row + range.rowCount; i++) {
sheet.setRowHeight(i, 40);
}
for (var i = range.col; i < range.col + range.colCount; i++) {
sheet.autoFitColumn(i);
}
sheet.setColumnWidth(1, 30);
sheet.setColumnWidth(2, 300);
}
function getBaseApiUrl() {
return window.location.href.match(/http.+spreadjs\/SpreadJSTutorial\//)[0] + 'server/api';
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta name="spreadjs culture" content="zh-cn"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div id="ss"></div>
</html>
body, html {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
margin: 0;
padding: 0;
}
#ss {
width: 100%;
height: 100%;
}