Combo Chart

Data that's arranged in columns and rows can be plotted in a Combo Chart. Combo charts combine two or more chart types to make the data easy to read and understand.

There are two steps to create a combo chart via add series: 1. Create a column chart: 2. Add a series, and set its chart type. For example, you could add a line chart: Currently, the following combinations of chart types are supported Clustered column chart Stacked column chart 100% Stacked column chart Clustered bar chart Stacked bar chart 100% Stacked bar chart Line chart Stacked line chart 100% Stacked line chart Line with makers chart Stacked line with makers chart 100% Stacked line with makers chart Area chart Stacked area chart 100% Stacked area chart Pie chart Doughnut chart Scatter chart Scatter with smooth lines chart Scatter with smooth lines with makers chart Scatter with straight lines chart Scatter with straight lines with makers chart
import { Component, NgModule, enableProdMode } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { SpreadSheetsModule } from '@mescius/spread-sheets-angular'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-shapes"; import '@mescius/spread-sheets-charts'; import './styles.css'; @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { spread: GC.Spread.Sheets.Workbook; hostStyle = { width: '100%', height: '100%', overflow: 'hidden', float: 'left' }; initSpread($event: any) { this.spread = $event.spread; let spread = this.spread; let sheets = spread.sheets; spread.suspendPaint(); let sheet1 = sheets[0]; let sheet2 = sheets[1]; this.initSheet1(sheet1); this.initSheet2(sheet2); this.addFormControl(sheet2); let chart1 = this.initChart1(sheet1, GC.Spread.Sheets.Charts.ChartType.columnClusterd); //add chart chart1.title({ text: "Monthly Registration Number and Distribution of Men and Women" }); this.addSeriesLine(chart1, GC.Spread.Sheets.Charts.ChartType.lineMarkers); this.changColumnChartDataLabels(chart1); let chart2 = this.initChart2(sheet2, GC.Spread.Sheets.Charts.ChartType.doughnut); //add chart chart2.title({ text: "Gauge Chart" }); this.adjustDoughnutSeries(chart2); this.addDoughnutSeries(chart2); this.addPieSeries(chart2) spread.resumePaint(); } initSheet1(sheet: GC.Spread.Sheets.Worksheet) { //prepare data for chart let dataArray = [ ["", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"], ["MAN", 327, 1776, 507, 1200, 800, 482, 204, 1390, 1001, 951, 381, 220], ["WOMEN", 709, 1917, 2455, 2610, 1719, 1433, 1544, 3285, 5208, 3372, 2484, 4078], ["TOTAL", 1036, 3693, 2962, 3810, 2519, 1915, 1748, 4675, 6209, 4323, 2865, 4298] ]; sheet.setArray(0, 0, dataArray); sheet.name("Normal Combo Chart"); } initSheet2(sheet: GC.Spread.Sheets.Worksheet) { let dataArray1 = [ ['Performance Label', 'Value'], ["Poor", 20], ["Average", 50], ["Good", 20], ["Excellent", 10], ["Total", 100], ]; sheet.setArray(0, 0, dataArray1); sheet.tables.add('table1', 0, 0, 6, 2, GC.Spread.Sheets.Tables.TableThemes.light1); let dataArray2 = [ ["Labels", "Values"], [10, 10], [20, 10], [30, 10], [40, 10], [50, 10], [60, 10], [70, 10], [80, 10], [90, 10], [100, 10], ["Total", 100], ]; sheet.setArray(0, 3, dataArray2); sheet.tables.add('table2', 0, 3, 11, 2, GC.Spread.Sheets.Tables.TableThemes.light1); let dataArray3 = [ ["Labels", "Values"], ["Pointer", 45], ["Thickness", 2], ["Rest", 154], ]; sheet.setArray(0, 6, dataArray3); sheet.tables.add('table3', 0, 6, 4, 2, GC.Spread.Sheets.Tables.TableThemes.medium7); sheet.setFormula(3, 7, "=200-H2-H3"); sheet.name("Gauge Chart"); } initChart1(sheet: GC.Spread.Sheets.Worksheet, type: GC.Spread.Sheets.Charts.ChartType) { return sheet.charts.add((sheet.name() + 'Chart2'), type, 30, 120, 900, 300, "A1:M3", GC.Spread.Sheets.Charts.RowCol.rows); } initChart2(sheet: GC.Spread.Sheets.Worksheet, type: GC.Spread.Sheets.Charts.ChartType) { return sheet.charts.add((sheet.name() + 'Chart1'), type, 0, 250, 800, 450, "A1:B6", GC.Spread.Sheets.Charts.RowCol.column); } //add a line type to create combo chart addSeriesLine(chart: GC.Spread.Sheets.Charts.Chart, type: GC.Spread.Sheets.Charts.ChartType) { let seriesItem: any = {}; seriesItem.chartType = type; seriesItem.border = { width: 3 }; seriesItem.name = 'A4'; seriesItem.xValues = 'B1:M1'; seriesItem.yValues = 'B4:M4'; chart.series().add(seriesItem); } //show dataLabels changColumnChartDataLabels(chart: GC.Spread.Sheets.Charts.Chart) { let dataLabels = chart.dataLabels(); dataLabels.showValue = true; dataLabels.showSeriesName = false; dataLabels.showCategoryName = false; let dataLabelPosition = GC.Spread.Sheets.Charts.DataLabelPosition; dataLabels.position = dataLabelPosition.above; chart.dataLabels(dataLabels); } //add a form control addFormControl(sheet: GC.Spread.Sheets.Worksheet) { let spinButton = sheet.shapes.addFormControl("spin button", GC.Spread.Sheets.Shapes.FormControlType.spinButton, 650, 300, 100, 60); let options = spinButton.options(); options.minValue = 0; options.maxValue = 100; options.step = 1; options.cellLink = "H2"; spinButton.options(options); spinButton.value(25); } //add a form control adjustDoughnutSeries(chart: GC.Spread.Sheets.Charts.Chart) { let doughnutSeries1 = chart.series().get(0); doughnutSeries1.startAngle = 270; let dataLabels = doughnutSeries1.dataLabels || {}; dataLabels.showCategoryName = true let dataLabelPosition = GC.Spread.Sheets.Charts.DataLabelPosition; dataLabels.position = dataLabelPosition.outsideEnd; doughnutSeries1.dataPoints[0] = { backColor: "rgb(192,0,0)" } doughnutSeries1.dataPoints[1] = { backColor: "rgb(255,255,0)" } doughnutSeries1.dataPoints[2] = { backColor: "rgb(68,144,96)" } doughnutSeries1.dataPoints[3] = { backColor: "rgb(112,173,71)" } doughnutSeries1.dataPoints[4] = { backColor: "" } chart.series().set(0, doughnutSeries1); let legend = chart.legend(); legend.visible = false; chart.legend(legend); } addDoughnutSeries(chart: GC.Spread.Sheets.Charts.Chart) { let doughnutSeries2: any = {}; doughnutSeries2.chartType = GC.Spread.Sheets.Charts.ChartType.doughnut; doughnutSeries2.name = 'D1'; doughnutSeries2.yValues = 'E2:E12'; doughnutSeries2.startAngle = 270; doughnutSeries2.doughnutHoleSize = 0.5; doughnutSeries2.dataPoints = { 0: { backColor: "rgb(231,230,230)", }, 1: { backColor: "rgb(231,230,230)", }, 2: { backColor: "rgb(231,230,230)", }, 3: { backColor: "rgb(231,230,230)", }, 4: { backColor: "rgb(231,230,230)", }, 5: { backColor: "rgb(231,230,230)", }, 6: { backColor: "rgb(231,230,230)", }, 7: { backColor: "rgb(231,230,230)", }, 8: { backColor: "rgb(231,230,230)", }, 9: { backColor: "rgb(231,230,230)", }, 10: { backColor: "", }, } chart.series().add(doughnutSeries2); } addPieSeries(chart: GC.Spread.Sheets.Charts.Chart) { let pieSeries: any = {}; pieSeries.chartType = GC.Spread.Sheets.Charts.ChartType.pie; pieSeries.name = 'G1'; pieSeries.xValues = 'G2:G4'; pieSeries.yValues = 'H2:H4'; pieSeries.axisGroup = GC.Spread.Sheets.Charts.AxisGroup.secondary; pieSeries.startAngle = 270; pieSeries.dataPoints = { 0: { backColor: "", }, 1: { backColor: "red", }, 2: { backColor: "", }, } chart.series().add(pieSeries); } } @NgModule({ imports: [BrowserModule, SpreadSheetsModule], declarations: [AppComponent], exports: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule);
<!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/angular/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- Polyfills --> <script src="$DEMOROOT$/en/angular/node_modules/core-js/client/shim.min.js"></script> <script src="$DEMOROOT$/en/angular/node_modules/zone.js/fesm2015/zone.min.js"></script> <!-- SystemJS --> <script src="$DEMOROOT$/en/angular/node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.import('@angular/compiler'); System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('$DEMOROOT$/en/lib/angular/license.ts'); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html>
<div class="sample-tutorial"> <gc-spread-sheets [hostStyle]="hostStyle" (workbookInitialized)="initSpread($event)"> <gc-worksheet></gc-worksheet> <gc-worksheet></gc-worksheet> </gc-spread-sheets> </div>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
(function (global) { System.config({ transpiler: 'ts', typescriptOptions: { tsconfig: true }, meta: { 'typescript': { "exports": "ts" }, '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'core-js': 'npm:core-js/client/shim.min.js', 'zone': 'npm:zone.js/fesm2015/zone.min.js', 'rxjs': 'npm:rxjs/dist/bundles/rxjs.umd.min.js', '@angular/core': 'npm:@angular/core/fesm2022', '@angular/common': 'npm:@angular/common/fesm2022/common.mjs', '@angular/compiler': 'npm:@angular/compiler/fesm2022/compiler.mjs', '@angular/platform-browser': 'npm:@angular/platform-browser/fesm2022/platform-browser.mjs', '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/fesm2022/platform-browser-dynamic.mjs', '@angular/common/http': 'npm:@angular/common/fesm2022/http.mjs', '@angular/router': 'npm:@angular/router/fesm2022/router.mjs', '@angular/forms': 'npm:@angular/forms/fesm2022/forms.mjs', 'jszip': 'npm:jszip/dist/jszip.min.js', 'typescript': 'npm:typescript/lib/typescript.js', 'ts': './plugin.js', 'tslib':'npm:tslib/tslib.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js', '@mescius/spread-sheets-charts': 'npm:@mescius/spread-sheets-charts/index.js', '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-angular': 'npm:@mescius/spread-sheets-angular/fesm2020/mescius-spread-sheets-angular.mjs', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'ts' }, rxjs: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, "node_modules/@angular": { defaultExtension: 'mjs' }, "@mescius/spread-sheets-angular": { defaultExtension: 'mjs' }, '@angular/core': { defaultExtension: 'mjs', main: 'core.mjs' } } }); })(this);