Overview

Visualize your data using the most popular spreadsheet charts. Supported charts include Column, Line, Pie, Area, Bar, XYScatter, Stock, Combo, Radar, Sunburst, Treemap with additional support for trendlines, error bars, and other customizations. The charts can also be imported or export to Excel files.

To use the chart feature, add the js file link into the document's head section: You can create a chart with the sheet.charts.add method, as shown below: You can get a chart in the sheet using the sheet.charts.get method, remove a chart using the sheet.charts.remove method, and/or also clear all your charts using the sheet.charts.clear method. A chart is built with many sub-elements, and you can customize each one using the chart API: Chart Title: The title of the chart You can get or set the text, the background color, the foreground color, the font, and the font size of the chart title. Series: The data points of a data series that are plotted on the chart You can get, add, or remove a series item from the series collection of a chart, as well as customize the name, border, width, border color, y value, x value, and fill color of each series item. Data Labels: You can use data labels to identify the details of a data point in a data series You can customize the chart’s series data labels style between below options showValue showSeriesName showCategoryName showPercentage separator position format color transparency backColor backColorTransparency borderColor borderWidth borderColorTransparency SpreadJS provides 28 chart types. You can get or set the current chart type using the following code: SpreadJS support display blank cells as below ways and diaplay #N/A cells as blank in chart. gaps: Null values are skipped. zero: Null values are treated as having a value of zero. connected: Null values are skipped and the line of the area chart is connected. SpreadJS support show or ignore hidden row and columns in chart. SpreadJS support preserve or ignore unsupported chart type when import.
import * as React from 'react'; import * as ReactDOM from 'react-dom'; import GC from '@grapecity/spread-sheets'; import { SpreadSheets, Worksheet } from '@grapecity/spread-sheets-react'; import '@grapecity/spread-sheets-charts'; import './styles.css'; const Component = React.Component; const chartType = [ [{ typeDesc: 'Clustered Column', type:GC.Spread.Sheets.Charts.ChartType.columnClustered },{ typeDesc: 'Stacked Column', type:GC.Spread.Sheets.Charts.ChartType.columnStacked },{ typeDesc: '100% Stacked Column', type:GC.Spread.Sheets.Charts.ChartType.columnStacked100 }], [{ typeDesc: 'Line', type:GC.Spread.Sheets.Charts.ChartType.line },{ typeDesc: 'Stacked Line', type:GC.Spread.Sheets.Charts.ChartType.lineStacked },{ typeDesc: '100% Stacked Line', type:GC.Spread.Sheets.Charts.ChartType.lineStacked100 },{ typeDesc: 'Line With Markers', type:GC.Spread.Sheets.Charts.ChartType.lineMarkers },{ typeDesc: 'Stacked Line With Markers', type:GC.Spread.Sheets.Charts.ChartType.lineMarkersStacked },{ typeDesc: '100% Stacked Line With Markers', type:GC.Spread.Sheets.Charts.ChartType.lineMarkersStacked100 }], [{ typeDesc: 'Pie', type:GC.Spread.Sheets.Charts.ChartType.pie },{ typeDesc: 'Doughnut', type:GC.Spread.Sheets.Charts.ChartType.doughnut }], [{ typeDesc: 'Clustered Bar', type:GC.Spread.Sheets.Charts.ChartType.barClustered },{ typeDesc: 'Stacked Bar', type:GC.Spread.Sheets.Charts.ChartType.barStacked },{ typeDesc: '100% Stacked Bar', type:GC.Spread.Sheets.Charts.ChartType.barStacked100 }], [{ typeDesc: 'Area', type:GC.Spread.Sheets.Charts.ChartType.area },{ typeDesc: 'Stacked Area', type:GC.Spread.Sheets.Charts.ChartType.areaStacked },{ typeDesc: '100% Stacked Area', type:GC.Spread.Sheets.Charts.ChartType.areaStacked100 }], [{ typeDesc: 'Scatter', type:GC.Spread.Sheets.Charts.ChartType.xyScatter },{ typeDesc: 'Scatter With Smooth Lines And Markers', type:GC.Spread.Sheets.Charts.ChartType.xyScatterSmooth },{ typeDesc: 'Scatter With Smooth Lines', type:GC.Spread.Sheets.Charts.ChartType.xyScatterSmoothNoMarkers },{ typeDesc: 'Scatter With Straight Lines And Markers', type:GC.Spread.Sheets.Charts.ChartType.xyScatterLines },{ typeDesc: 'Scatter With Straight Lines', type:GC.Spread.Sheets.Charts.ChartType.xyScatterLinesNoMarkers },{ typeDesc: 'Bubble', type:GC.Spread.Sheets.Charts.ChartType.bubble }], [{ typeDesc: 'High-Low-Close', type:GC.Spread.Sheets.Charts.ChartType.stockHLC },{ typeDesc: 'Open-High-Low-Close', type:GC.Spread.Sheets.Charts.ChartType.stockOHLC },{ typeDesc: 'Volume-High-Low-Close', type:GC.Spread.Sheets.Charts.ChartType.stockVHLC },{ typeDesc: 'Volume-Open-High-Low-Close', type:GC.Spread.Sheets.Charts.ChartType.stockVOHLC }] ]; function _getElementById(id) { return document.getElementById(id); } class App extends Component { constructor(props) { super(props); this.spread = null; } render() { return (<div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}> <Worksheet/> </SpreadSheets> </div> <Panel insertChart={(e) => { this.insertChart(e) }} switchRowColumn={(e) => { this.switchRowColumn(e) }} removeChart={(e) => { this.removeChart(e) }} removeAllChart={(e) => { this.removeAllChart(e) }} changeTypeSelect={(e) => { this.changeTypeSelect(e) }} displayBlanksCells={(e) => { this.displayBlanksCells(e) }} showNAAsBlanks={(e) => { this.showNAAsBlanks(e) }} ignoreHiddenRowAndColumn={(e) => { this.ignoreHiddenRowAndColumn(e) }} /> </div>); } initSpread(spread) { this.spread = spread; spread.suspendPaint(); spread.setSheetCount(2); let sheet1 = spread.getSheet(0); sheet1.name("Common Chart"); let sheet2 = spread.getSheet(1); sheet2.name("Custom Chart"); this.initSheet(sheet1); this.initSheet(sheet2); //add chart this.initChart(sheet1); this.initChart(sheet2); //custom chart this.customChartStyle(sheet2); spread.resumePaint(); this.changeTypeSelect(); } initSheet(sheet) { sheet.suspendPaint(); //prepare data for chart let dataArray = [ ["", 'Chrome', 'FireFox', 'IE', 'Safari', 'Edge', 'Opera', 'Other'], ["2015", 0.5651, 0.1734, 0.1711, 0.427, 0, 0.184, 0.293], ["2016", 0.6230, 0.1531, 0.1073, 0.464, 0.311, 0.166, 0.225], ["2017", 0.6360, 0.1304, 0.834, 0.589, 0.443, 0.223, 0.246] ]; sheet.setArray(0, 0, dataArray); sheet.resumePaint(); } initChart(sheet) { //add common chart sheet.charts.add('Chart1', GC.Spread.Sheets.Charts.ChartType.columnClustered, 0, 100, 800, 300, "A1:H4"); } customChartStyle(sheet) { let changeChart = sheet.charts.all()[0]; this.changeChartStyle(changeChart); } changeChartStyle(chart) { //change orientation this.switchOrientation(chart); //change legend this.changeChartLegend(chart); //change chartArea this.changeChartArea(chart); //change chartTitle this.changeChartTitle(chart); //change dataLabels this.changeChartDataLabels(chart); //change axisTitles this.changeChartAxisTitles(chart); //change axesLine this.changeChartAxesLine(chart); //change series this.changeSeries(chart); //change gridLine this.changeGridLine(chart); //change seriesBorder this.changeSeriesBorder(chart); } switchOrientation(chart) { chart.switchDataOrientation(); } changeChartLegend(chart) { let legend = chart.legend(); legend.visible = true; let legendPosition = GC.Spread.Sheets.Charts.LegendPosition; legend.position = legendPosition.top; chart.legend(legend); } changeChartArea(chart) { let chartArea = chart.chartArea(); chartArea.backColor = "rgba(93,93,93,1)"; chartArea.color = "rgba(255,255,255,1)"; chartArea.fontSize = 14; chart.chartArea(chartArea); } changeChartTitle(chart) { let title = chart.title(); title.text = "Browser Market Share"; title.fontSize = 18; chart.title(title); } changeChartDataLabels(chart) { let dataLabels = chart.dataLabels(); dataLabels.showValue = true; dataLabels.showSeriesName = false; dataLabels.showCategoryName = false; dataLabels.format = "0.00%"; let dataLabelPosition = GC.Spread.Sheets.Charts.DataLabelPosition; dataLabels.position = dataLabelPosition.outsideEnd; chart.dataLabels(dataLabels); let series0 = chart.series().get(0); series0.dataLabels = { showSeriesName: true, showCategoryName: true, separator: ";", position: GC.Spread.Sheets.Charts.DataLabelPosition.Center, color: "red", backColor: "white", borderColor: "blue", borderWidth: 2 }; chart.series().set(0, series0); let series2 = chart.series().get(2); series2.dataLabels = { showSeriesName: true, separator: "/", position: GC.Spread.Sheets.Charts.DataLabelPosition.insideEnd, color: "yellow", backColor: "white", borderColor: "green", borderWidth: 1 }; chart.series().set(2, series2); let series4 = chart.series().get(4); series4.dataLabels = { showCategoryName: true, separator: ":", position: GC.Spread.Sheets.Charts.DataLabelPosition.above, color: "blue", backColor: "white", borderColor: "red", borderWidth: 2.5 }; chart.series().set(4, series4); } changeChartAxisTitles(chart) { let axes = chart.axes(); axes.primaryCategory.title.text = 'Year'; axes.primaryCategory.title.fontSize = 14; chart.axes(axes); } changeChartAxesLine(chart) { let axes = chart.axes(); axes.primaryValue.format = "0%"; chart.axes(axes); } changeSeries(chart) { let series = chart.series(); let seriesItem = series.get(6); seriesItem.backColor = "#a3cf62"; series.set(6, seriesItem); } changeGridLine(chart) { let axes = chart.axes(); axes.primaryCategory.majorGridLine.visible = false; axes.primaryValue.majorGridLine.visible = false; chart.axes(axes); } changeSeriesBorder(chart) { let series = chart.series().get(); for (let i = 0; i < series.length; i++) { let seriesItem = series[i]; seriesItem.border.color = 'rgb(255,255,255)'; seriesItem.border.width = 1; chart.series().set(i, seriesItem); } } getActiveChart(sheet) { let activeChart = null; sheet.charts.all().forEach(function (chart) { if (chart.isSelected()) { activeChart = chart; } }); return activeChart; } judgeIsEmptyOneCell(sheet, range) { if (range && range.rowCount === 1 && range.colCount === 1) { let cell = sheet.getCell(range.row, range.col); if (!cell.text()) { return true; } } return false; } changeTypeSelect(e) { let index = parseInt(e && e.target.value || 0); if (index !== null && index !== undefined && index < chartType.length) { _getElementById('typeSelect').innerHTML = ''; let typeArray = chartType[index]; for (let i = 0; i < typeArray.length; i++) { let item = typeArray[i]; let option = document.createElement('option'); let value = document.createAttribute('value'); value.nodeValue = i; option.setAttributeNode(value); option.innerHTML = item.typeDesc; _getElementById('typeSelect').appendChild(option); } } } insertChart(chartInfo) { let activeSheet = this.spread.getActiveSheet(); let dataRange = activeSheet.getSelections()[0]; if (!this.judgeIsEmptyOneCell(activeSheet, dataRange)) { let rangeToFormula = GC.Spread.Sheets.CalcEngine.rangeToFormula; let dataFormula = rangeToFormula(dataRange); let groupIndex = parseInt(chartInfo.groupType); let typeIndex = parseInt(chartInfo.chartType); if (groupIndex < chartType.length) { let typeArray = chartType[groupIndex]; if (typeIndex < typeArray.length) { let type = typeArray[typeIndex].type; try { activeSheet.charts.add('', type, 30, 120, 500, 300, dataFormula, GC.Spread.Sheets.Charts.RowCol.rows); } catch (e) { alert(e.message); } } } } } switchRowColumn(e) { let activeSheet = this.spread.getActiveSheet(); let activeChart = this.getActiveChart(activeSheet); if (activeChart) { let isSwitched = activeChart.switchDataOrientation(); if (!isSwitched) { alert("'Can't switch row/column"); } } } removeChart() { let activeSheet = this.spread.getActiveSheet(); let activeChart = this.getActiveChart(activeSheet); if (activeChart) { activeSheet.charts.remove(activeChart.name()); } } removeAllChart() { let activeSheet = this.spread.getActiveSheet(); activeSheet.charts.clear(); } ignoreHiddenRowAndColumn(e) { let activeSheet = this.spread.getActiveSheet(); let activeChart = this.getActiveChart(activeSheet); activeChart && activeChart.ignoreHidden(e.target.checked); } displayBlanksCells(e) { let activeSheet = this.spread.getActiveSheet(); let activeChart = this.getActiveChart(activeSheet); let index = parseInt(e.target.value); if (index !== null && index !== undefined) { activeChart && activeChart.displayBlanksAs(index); } } showNAAsBlanks(e) { let activeSheet = this.spread.getActiveSheet(); let activeChart = this.getActiveChart(activeSheet); activeChart && activeChart.displayNaNAsBlank(e.target.checked); } } class Panel extends Component { constructor(props) { super(props); this.state = { groupType: '0', chartType: '0' } } render() { return ( <div class="options-container"> <p>Highlight a range of cells, select a chart group and chart type then click “Add Chart” to add the chart to the sheet. Switch the axes with “Switch row/column” or remove the chart(s) with “Remove chart” or “Remove all charts”. </p> <div class="option-row"> <label>Group:</label> <select id="groupSelect" style={{width: "160px"}} value = {this.state.groupType} onChange={(e) => { this.setState({groupType: e.target.value}) this.props.changeTypeSelect(e); }}> <option value="0">Column</option> <option value="1">Line</option> <option value="2">Pie</option> <option value="3">Bar</option> <option value="4">Area</option> <option value="5">Scatter</option> <option value="6">Stock</option> </select> </div> <div class="option-row"> <label>Type:</label> <select id="typeSelect" style={{width: "160px"}} value = {this.state.chartType} onChange={(e) => { this.setState({chartType: e.target.value}) }}></select> </div> <div class="option-row"> <input type="button" style={{width: "150px", margin:"5px", "margin-bottom": "15px"}} value="Add Chart" id="insertChart" onClick={(e) => { this.props.insertChart(this.state) }} /> <input type="button" style={{width: "150px", margin:"5px"}} value="Switch row/column" id="switchRowColumn" onClick={(e) => { this.props.switchRowColumn(e) }} /> <input type="button" style={{width: "150px", margin:"5px"}} value="Remove chart" id="removeChart" onClick={(e) => { this.props.removeChart(e) }} /> <input type="button" style={{width: "150px", margin:"5px"}} value="Remove all charts" id="removeAllCharts" onClick={(e) => { this.props.removeAllChart(e) }} /> </div> <div class="option-row"> <label>Display Blanks Cells As:</label> <select id="displayBlanksCells" style={{width: "80px"}} onChange={(e) => { this.props.displayBlanksCells(e) }}> <option value="1" selected="selected">Gaps</option> <option value="2">Zero</option> <option value="0">Connect</option> </select> </div> <div class="option-row"> <input type="checkbox" id="showNAAsBlanks" onClick={(e) => { this.props.showNAAsBlanks(e) }}></input> <label for="showNAAsBlanks">Display #N/A Cells As Blank Cells</label> </div> <div class="option-row"> <input type="checkbox" id="ignoreHidden" checked onClick={(e) => { this.props.ignoreHiddenRowAndColumn(e) }}></input> <label for="ignoreHidden">Ingore Hidden Rows And Columns</label> </div> </div> ) } } ReactDOM.render(<App />, _getElementById('app'));
<!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/react/node_modules/@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('$DEMOROOT$/en/lib/react/license.js').then(function () { System.import('./src/app'); }); </script> </head> <body> <div id="app"></div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 2px; margin-top: 2px; } .sample-options { z-index: 1000; } label { margin-bottom: 6px; } p{ padding:2px 10px; background-color:lavender; } input { padding: 2px 6px; } input[type=button] { margin-top: 6px; display: block; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } #app { height: 100%; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@grapecity/spread-sheets-charts': 'npm:@grapecity/spread-sheets-charts/index.js', '@grapecity/spread-sheets': 'npm:@grapecity/spread-sheets/index.js', '@grapecity/spread-sheets-react': 'npm:@grapecity/spread-sheets-react/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'react': 'npm:react/umd/react.production.min.js', 'react-dom': 'npm:react-dom/umd/react-dom.production.min.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' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);