Error Bars

Error bars allow you to quickly display margins of error and standard deviations in your charts.

The demo is being dynamically compiled to support real-time code editing... For quicker access to features, switch to the "JavaScript" tab for a smoother experience! :)
Description
app.component.ts
index.html
app.component.html
styles.css
Copy to CodeMine

When using charts to display data, it can be useful to display margins of error for each point. Showing a positive or negative error amount in the results of a scientific experiment can show the variability of the results at a glance.

The error type (error amount) can be set with the following:

  • Fixed Value - set error bar with a fixed value.
  • Percentage - set error bar with a percentage of the data value in the same direction axis.
  • Standard deviation - set error bar with a calculating value which depends on the set deviation and chart data value.
  • Standard error - set error bar with a calculating value which only depends on the chart data value.
  • Custom - set error bar with positive and negative values represented by formulas or fixed numbers.

This feature supports the following chart types:

  • Column
  • Line
  • Bar
  • Area
  • Scatter
  • Bubble

Customize

type: Specify the visibility of negative error bar and positive error bar.

noEndCap: Specify the visibility of the error bar caps.

style: Specify the line style of the error bar including color, width, and dash line.

You can customize the error bars using the following code:

    var series = chart.series().get(0);
    series.errorBars = {
        horizontal: {
            type: GC.Spread.Sheets.Charts.ErrorBarType.both,
            valueType: GC.Spread.Sheets.Charts.ErrorBarValueType.fixedValue,
            value: 0.4, // error bar value
            noEndCap: true,
            style: {
                width: 4, // line width
                dashStyle: GC.Spread.Sheets.Charts.LineDashStyle.dash
            }
        },
        vertical: {
            type: GC.Spread.Sheets.Charts.ErrorBarType.minus,
            valueType: GC.Spread.Sheets.Charts.ErrorBarValueType.percentage,
            value: 90, // 90%
            style: {
                color: 'red' // line color
            }
        }
    };
    chart.series().set(0, series);
When using charts to display data, it can be useful to display margins of error for each point. Showing a positive or negative error amount in the results of a scientific experiment can show the variability of the results at a glance. The error type (error amount) can be set with the following: Fixed Value - set error bar with a fixed value. Percentage - set error bar with a percentage of the data value in the same direction axis. Standard deviation - set error bar with a calculating value which depends on the set deviation and chart data value. Standard error - set error bar with a calculating value which only depends on the chart data value. Custom - set error bar with positive and negative values represented by formulas or fixed numbers. This feature supports the following chart types: Column Line Bar Area Scatter Bubble Customize type: Specify the visibility of negative error bar and positive error bar. noEndCap: Specify the visibility of the error bar caps. style: Specify the line style of the error bar including color, width, and dash line. You can customize the error bars using the following code:
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'; const COLORS = { deepBlue: '#3e619f', blue: '#a1b8e1', deepOrange: '#c55a11', orange: '#f6be98', white: '#ffffff' }; @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; spread.setSheetCount(3); this.addBasicChart(spread.getSheet(0)); this.addStepChart(spread.getSheet(1)); this.addGanttChart(spread.getSheet(2)); } addBasicChart(sheet: GC.Spread.Sheets.Worksheet) { sheet.name("BaseUsage"); let salesData = [ ['', 'Sales'], ['Jan', 54], ['Feb', 60], ['Mar', 86], ['Apr', 92], ['May', 112], ['Jun', 157], ['Jul', 202], ['Aug', 195], ['Sep', 187], ['Oct', 194], ['Nov', 238], ['Dec', 289], ]; sheet.setArray(0, 0, salesData); let chart1 = sheet.charts.add("chart1", GC.Spread.Sheets.Charts.ChartType.xyScatterSmooth, 140, 5, 500, 350, "A1:B13", GC.Spread.Sheets.Charts.RowCol.columns); let series = chart1.series().get(0); series.errorBars = { vertical: { type: GC.Spread.Sheets.Charts.ErrorBarType.both, valueType: GC.Spread.Sheets.Charts.ErrorBarValueType.standardError, style: { color: COLORS.deepOrange } } }; chart1.series().set(0, series); } addStepChart(sheet: GC.Spread.Sheets.Worksheet) { sheet.name("StepChart"); let priceData = [ ['', 'Price', 'x-error', 'y-error-negative', 'y-error-positive'], [new Date('5/7/2019'), 39], [new Date('5/27/2019'), 47], [new Date('6/15/2019'), 30], [new Date('6/24/2019'), 46], [new Date('8/3/2019'), 37], [new Date('8/28/2019'), 50], [new Date('9/29/2019'), 43], [new Date('10/30/2019'), 48], ]; sheet.setArray(0, 0, priceData); sheet.setFormula(1, 2, "=IF(A3, A3-A2, 20)"); sheet.setFormula(1, 3, "=IFERROR(IF(B1-B2>0, B1-B2, 0), 0)"); sheet.setFormula(1, 4, "=IFERROR(IF(B2-B1>0, B2-B1, 0), 0)"); sheet.fillAuto(new GC.Spread.Sheets.Range(1, 2, 1, 3), new GC.Spread.Sheets.Range(1, 2, 8, 3), { direction: GC.Spread.Sheets.Fill.FillDirection.down, fillType: GC.Spread.Sheets.Fill.FillType.auto }); sheet.getRange(1, 1, 8, 1).formatter('_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)'); sheet.setColumnWidth(0, 100); let chart = sheet.charts.add("StepChart", GC.Spread.Sheets.Charts.ChartType.xyScatter, 160, 5, 800, 450, "A1:B9", GC.Spread.Sheets.Charts.RowCol.columns); let axes = chart.axes(); axes.primaryCategory.format = 'm/d/yyyy'; axes.primaryCategory.majorTickPosition = GC.Spread.Sheets.Charts.TickMark.outside; chart.axes(axes); chart.legend({ visible: false }); let series = chart.series().get(0); series.symbol = { fill: null, border: { color: null } }; // Hide the symbol. series.errorBars = { horizontal: { type: GC.Spread.Sheets.Charts.ErrorBarType.plus, valueType: GC.Spread.Sheets.Charts.ErrorBarValueType.custom, noEndCap: true, custom: { positive: '=StepChart!$C$2:$C$9' } }, vertical: { valueType: GC.Spread.Sheets.Charts.ErrorBarValueType.custom, noEndCap: true, custom: { positive: '=StepChart!$D$2:$D$9', negative: '=StepChart!$E$2:$E$9' }, style: { color: "gray", dashStyle: GC.Spread.Sheets.Charts.LineDashStyle.dash } } }; chart.series().set(0, series); let dataLabels = chart.dataLabels(); dataLabels.showValue = true; dataLabels.position = GC.Spread.Sheets.Charts.DataLabelPosition.above; dataLabels.format = '$* #,##0.00'; dataLabels.color = "red"; chart.dataLabels(dataLabels); } addGanttChart(sheet: GC.Spread.Sheets.Worksheet) { let self = this; sheet.name("GanttChart"); let ganttData = [ ['End Date', 'Height'], [new Date('4/15/2019'), 0.9375], [new Date('4/29/2019'), 0.8125], [new Date('5/6/2019'), 0.6875], [new Date('5/20/2019'), 0.5625], [new Date('5/27/2019'), 0.4375], [new Date('6/17/2019'), 0.3125], [new Date('6/24/2019'), 0.1875], [new Date('7/1/2019'), 0.0625] ]; sheet.setArray(0, 0, ganttData); sheet.setColumnWidth(0, 100); let SIZE = 12; let ZFACTOR = 25; let chart = sheet.charts.add("GanttChart", GC.Spread.Sheets.Charts.ChartType.xyScatter, 180, 5, 500, 350, "A1:B9", GC.Spread.Sheets.Charts.RowCol.columns); chart.title({ text: 'Advanced Gantt Chart' }); let axes = chart.axes(); axes.primaryCategory.format = 'm/d/yyyy'; axes.primaryCategory.majorTickPosition = GC.Spread.Sheets.Charts.TickMark.outside; axes.primaryValue.visible = false; chart.axes(axes); chart.legend({ visible: false }); let backgroundSeriesIndex = 0; let backgroundSeries = chart.series().get(backgroundSeriesIndex); let backgroundErrorBar = { type: GC.Spread.Sheets.Charts.ErrorBarType.minus, valueType: GC.Spread.Sheets.Charts.ErrorBarValueType.custom, noEndCap: true, custom: { negative: '={' + ZFACTOR + '}' }, style: { color: COLORS.blue, width: SIZE } }; backgroundSeries.errorBars = { horizontal: backgroundErrorBar }; backgroundSeries.symbol = { shape: GC.Spread.Sheets.Charts.SymbolShape.diamond, size: SIZE, fill: COLORS.deepBlue }; chart.series().set(backgroundSeriesIndex, backgroundSeries); let unfinishedSeries = { chartType: GC.Spread.Sheets.Charts.ChartType.xyScatter, axisGroup: GC.Spread.Sheets.Charts.AxisGroup.primary, xValues: 'GanttChart!$A$2:$A$9', yValues: 'GanttChart!$B$2:$B$9', symbol: { shape: GC.Spread.Sheets.Charts.SymbolShape.diamond, size: SIZE - 4, fill: COLORS.deepOrange }, errorBars: { horizontal: { type: GC.Spread.Sheets.Charts.ErrorBarType.minus, valueType: GC.Spread.Sheets.Charts.ErrorBarValueType.custom, noEndCap: true, custom: { negative: '={' + self.createErrorBarValue(ganttData.slice(1), ZFACTOR).toString() + '}' }, style: { color: COLORS.orange, width: SIZE } } } }; chart.series().add(unfinishedSeries); let dataLabels = chart.dataLabels(); dataLabels.showValue = true; dataLabels.position = GC.Spread.Sheets.Charts.DataLabelPosition.below; dataLabels.format = '#,##0%'; dataLabels.color = COLORS.orange; chart.dataLabels(dataLabels); } createErrorBarValue(dataSource: any, z: number) { let values = []; for (let i = 0; i < dataSource.length; i++) { values.push(dataSource[i][1] * z); } return values; } } @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-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-shapes': 'npm:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-charts': 'npm:@mescius/spread-sheets-charts/index.js', '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/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);