Hierarchical Category

This sample demonstrates how to use hierarchical categories in Data Charts. Each sheet displays a different supported chart type with a multi-level category axis, grouping data by nested fields such as Country > City.

Data Charts support Hierarchical Category, which enables multi-level categorical axes in Cartesian coordinate charts. Define nested categories using the child property in the category encoding. Supported chart types include Column, Range Column, Stacked Column, Percent Stacked Column, Bar, Range Bar, Stacked Bar, Percent Stacked Bar, Area, Range Area, Stacked Area, Percent Stacked Area, Line, Candlestick, and OHLC. Each sheet in this sample showcases one of these chart types with a hierarchical category axis. Notes: Hierarchical Category is only applicable to axis-based (Cartesian) chart types. Non-axis charts such as Pie, Donut, Sunburst, Treemap, Funnel, and Waterfall do not support this feature.
window.onload = async () => { const { spread, designer } = createSpreadAndDesigner(); await initDataManager(spread); const DataChartType = GC.Spread.Sheets.DataCharts.DataChartType; const Aggregate = GC.Spread.Sheets.DataCharts.Aggregate; const chartConfigs = [ { name: 'Column', type: DataChartType.column, table: 'Sales', encoding: 'single' }, { name: 'Range Column', type: DataChartType.rangeColumn, table: 'Sales', encoding: 'range' }, { name: 'Stacked Column', type: DataChartType.stackedColumn, table: 'Sales', encoding: 'stacked' }, { name: 'Percent Stacked Column', type: DataChartType.percentStackedColumn, table: 'Sales', encoding: 'stacked' }, { name: 'Bar', type: DataChartType.bar, table: 'Sales', encoding: 'single' }, { name: 'Range Bar', type: DataChartType.rangeBar, table: 'Sales', encoding: 'range' }, { name: 'Stacked Bar', type: DataChartType.stackedBar, table: 'Sales', encoding: 'stacked' }, { name: 'Percent Stacked Bar', type: DataChartType.percentStackedBar, table: 'Sales', encoding: 'stacked' }, { name: 'Area', type: DataChartType.area, table: 'Sales', encoding: 'single' }, { name: 'Range Area', type: DataChartType.rangeArea, table: 'Sales', encoding: 'range' }, { name: 'Stacked Area', type: DataChartType.stackedArea, table: 'Sales', encoding: 'stacked' }, { name: 'Percent Stacked Area', type: DataChartType.percentStackedArea, table: 'Sales', encoding: 'stacked' }, { name: 'Line', type: DataChartType.line, table: 'Sales', encoding: 'single' }, { name: 'Candlestick', type: DataChartType.candlestick, table: 'Stock', encoding: 'ohlc' }, { name: 'OHLC', type: DataChartType.ohlc, table: 'Stock', encoding: 'ohlc' }, ]; spread.setSheetCount(chartConfigs.length); for (let i = 0; i < chartConfigs.length; i++) { const cfg = chartConfigs[i]; const sheet = spread.getSheet(i); sheet.name(cfg.name); addChartToSheet(sheet, cfg, Aggregate); } spread.setActiveSheetIndex(0); spread.getActiveSheet().dataCharts.all()[0].isSelected(true); if (designer) { designer.refresh(); } } function addChartToSheet(sheet, cfg, Aggregate) { const dataChart = sheet.dataCharts.add(cfg.name, 20, 20, 450, 300, cfg.type); let encodings; const hierarchicalCategory = { field: 'Region', child: { field: 'Salesman' } }; const ohlcHierarchicalCategory = { field: 'month', child: { field: 'day' } }; switch (cfg.encoding) { case 'single': encodings = { values: [{ field: 'Sales', aggregate: Aggregate.sum }], category: hierarchicalCategory, }; break; case 'range': encodings = { values: [{ vectors: { upper: { field: 'Sales' }, lower: { field: 'Return' }, }, aggregate: Aggregate.sum, }], category: hierarchicalCategory, }; break; case 'stacked': encodings = { values: [{ field: 'Sales', aggregate: Aggregate.sum }], category: hierarchicalCategory, color: { field: 'Product' }, }; break; case 'ohlc': encodings = { values: [{ vectors: { open: { field: 'open' }, high: { field: 'high' }, low: { field: 'low' }, close: { field: 'close' }, }, }], category: ohlcHierarchicalCategory, }; break; } dataChart.setChartConfig({ tableName: cfg.table, plots: [{ type: cfg.type, encodings: encodings, }], config: { header: { title: cfg.name + ' - Hierarchical Category', padding: { left: 10, right: 10, top: 10, bottom: 10 }, textStyle: { fontSize: 16, alignment: GC.Spread.Sheets.DataCharts.HAlign.left, }, }, }, }); } function createSpreadAndDesigner() { const demoHost = document.getElementById('demo-host'); if (window !== top) { const spread = new GC.Spread.Sheets.Workbook('spread-host', { sheetCount: 1 }); new GC.Spread.Sheets.DataCharts.DataChartConfigPanel('panel-host', spread); return { spread } } else { const designer = new GC.Spread.Sheets.Designer.Designer(demoHost, undefined, undefined, { sheetCount: 1 }); return { designer, spread: designer.getWorkbook(), } } } async function initDataManager(spread) { const dataManager = spread.dataManager(); await dataManager.addTable('Sales', { data: [ { Region: 'East', Salesman: 'Alice', Product: 'Laptop', Sales: 450, Return: 120 }, { Region: 'East', Salesman: 'Alice', Product: 'Phone', Sales: 320, Return: 85 }, { Region: 'East', Salesman: 'Bob', Product: 'Laptop', Sales: 380, Return: 95 }, { Region: 'East', Salesman: 'Bob', Product: 'Phone', Sales: 290, Return: 70 }, { Region: 'East', Salesman: 'Carol', Product: 'Laptop', Sales: 410, Return: 110 }, { Region: 'East', Salesman: 'Carol', Product: 'Phone', Sales: 350, Return: 90 }, { Region: 'West', Salesman: 'Dave', Product: 'Laptop', Sales: 520, Return: 140 }, { Region: 'West', Salesman: 'Dave', Product: 'Phone', Sales: 280, Return: 65 }, { Region: 'West', Salesman: 'Eve', Product: 'Laptop', Sales: 470, Return: 130 }, { Region: 'West', Salesman: 'Eve', Product: 'Phone', Sales: 310, Return: 80 }, { Region: 'West', Salesman: 'Frank', Product: 'Laptop', Sales: 390, Return: 100 }, { Region: 'West', Salesman: 'Frank', Product: 'Phone', Sales: 260, Return: 60 }, { Region: 'North', Salesman: 'Grace', Product: 'Laptop', Sales: 340, Return: 90 }, { Region: 'North', Salesman: 'Grace', Product: 'Phone', Sales: 270, Return: 75 }, { Region: 'North', Salesman: 'Hank', Product: 'Laptop', Sales: 430, Return: 115 }, { Region: 'North', Salesman: 'Hank', Product: 'Phone', Sales: 300, Return: 80 }, { Region: 'South', Salesman: 'Ivy', Product: 'Laptop', Sales: 480, Return: 125 }, { Region: 'South', Salesman: 'Ivy', Product: 'Phone', Sales: 330, Return: 85 }, { Region: 'South', Salesman: 'Jack', Product: 'Laptop', Sales: 360, Return: 95 }, { Region: 'South', Salesman: 'Jack', Product: 'Phone', Sales: 250, Return: 55 }, ], }).fetch(); await dataManager.addTable('Stock', { data: [ { month: 'Jan', day: 'Jan-01', open: 150.00, high: 155.20, low: 148.50, close: 153.80 }, { month: 'Jan', day: 'Jan-02', open: 153.80, high: 157.40, low: 152.10, close: 156.90 }, { month: 'Jan', day: 'Jan-03', open: 156.90, high: 158.60, low: 154.30, close: 155.20 }, { month: 'Jan', day: 'Jan-04', open: 155.20, high: 159.80, low: 154.00, close: 158.50 }, { month: 'Jan', day: 'Jan-05', open: 158.50, high: 162.30, low: 157.20, close: 161.00 }, { month: 'Feb', day: 'Feb-01', open: 161.00, high: 163.50, low: 159.80, close: 162.40 }, { month: 'Feb', day: 'Feb-02', open: 162.40, high: 165.70, low: 161.30, close: 164.80 }, { month: 'Feb', day: 'Feb-03', open: 164.80, high: 166.20, low: 162.50, close: 163.10 }, { month: 'Feb', day: 'Feb-04', open: 163.10, high: 167.90, low: 162.00, close: 167.30 }, { month: 'Feb', day: 'Feb-05', open: 167.30, high: 170.10, low: 166.50, close: 169.20 }, { month: 'Mar', day: 'Mar-01', open: 169.20, high: 172.40, low: 168.00, close: 171.50 }, { month: 'Mar', day: 'Mar-02', open: 171.50, high: 173.80, low: 169.60, close: 170.30 }, { month: 'Mar', day: 'Mar-03', open: 170.30, high: 174.50, low: 169.10, close: 173.90 }, { month: 'Mar', day: 'Mar-04', open: 173.90, high: 176.20, low: 172.30, close: 175.60 }, { month: 'Mar', day: 'Mar-05', open: 175.60, high: 178.00, low: 174.20, close: 176.80 }, ], }).fetch(); }
<!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/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.light.min.css"> <link rel="stylesheet" type="text/css" href="styles.css"> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-datacharts-addon/dist/gc.spread.sheets.datacharts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script> const designerDependencyScripts = [ '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer-resources-en/dist/gc.spread.sheets.designer.resource.en.min.js', '$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js', '$DEMOROOT$/spread/source/js/designer/license.js', ] function appendScriptNode (src) { const script = document.createElement('script'); script.src = src; script.async = false; script.type = 'text/javascript'; document.head.appendChild(script); } if (top === window) { // not in iframe designerDependencyScripts.forEach(appendScriptNode); } </script> <script src="app.js" type="text/javascript"></script> </head> <body> <div class="sample-tutorial"> <div id="demo-host"> <div id="spread-host"></div> <div id="panel-host"></div> </div> </div> </body> </html>
body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .sample-tutorial { position: relative; height: 100%; overflow: hidden; } #demo-host { width: 100%; height: 100%; overflow: hidden; float: left; } #spread-host { position: absolute; top: 0; left: 0; width: calc(100% - 380px); height: 100%; } #panel-host { position: absolute; top: 0; right: 0; width: 380px; height: 100%; }