| /******************************************************************************* | |
| * You may amend and distribute as you like, but don't remove this header! | |
| * | |
| * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. | |
| * See http://www.codeplex.com/EPPlus for details. | |
| * | |
| * Copyright (C) 2011 Jan Källman | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| * See the GNU Lesser General Public License for more details. | |
| * | |
| * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php | |
| * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html | |
| * | |
| * All code and executables are provided "as is" with no warranty either express or implied. | |
| * The author accepts no liability for any damage or loss of business that this product may cause. | |
| * | |
| * Code change notes: | |
| * | |
| * Author Change Date | |
| ******************************************************************************* | |
| * Jan Källman Added 2009-10-01 | |
| * Jan Källman License changed GPL-->LGPL 2011-12-16 | |
| *******************************************************************************/ | |
| using System; | |
| using System.Collections.Generic; | |
| using System.Text; | |
| using System.Xml; | |
| using System.Collections; | |
| using OfficeOpenXml.Table.PivotTable; | |
| namespace OfficeOpenXml.Drawing.Chart | |
| { | |
| public sealed class ExcelBubbleChartSeries : ExcelChartSeries | |
| { | |
| internal ExcelBubbleChartSeries(ExcelChart chart, XmlNamespaceManager ns, XmlNode node, bool isPivot) | |
| : base(chart,ns,node, isPivot) | |
| { | |
| //_chartSeries = new ExcelChartSeries(this, _drawings.NameSpaceManager, _chartNode, isPivot); | |
| } | |
| public ExcelChartSerie Add(ExcelRangeBase Serie, ExcelRangeBase XSerie, ExcelRangeBase BubbleSize) | |
| { | |
| return base.AddSeries(Serie.FullAddressAbsolute, XSerie.FullAddressAbsolute, BubbleSize.FullAddressAbsolute); | |
| } | |
| public ExcelChartSerie Add(string SerieAddress, string XSerieAddress, string BubbleSizeAddress) | |
| { | |
| return base.AddSeries(SerieAddress, XSerieAddress, BubbleSizeAddress); | |
| } | |
| } | |
| /// <summary> | |
| /// Collection class for chart series | |
| /// </summary> | |
| public class ExcelChartSeries : XmlHelper, IEnumerable | |
| { | |
| List<ExcelChartSerie> _list=new List<ExcelChartSerie>(); | |
| internal ExcelChart _chart; | |
| XmlNode _node; | |
| XmlNamespaceManager _ns; | |
| internal ExcelChartSeries(ExcelChart chart, XmlNamespaceManager ns, XmlNode node, bool isPivot) | |
| : base(ns,node) | |
| { | |
| _ns = ns; | |
| _chart=chart; | |
| _node=node; | |
| _isPivot = isPivot; | |
| SchemaNodeOrder = new string[] { "view3D", "plotArea", "barDir", "grouping", "scatterStyle", "varyColors", "ser", "explosion", "dLbls", "firstSliceAng", "holeSize", "shape", "legend", "axId" }; | |
| foreach(XmlNode n in node.SelectNodes("c:ser",ns)) | |
| { | |
| ExcelChartSerie s; | |
| if (chart.ChartNode.LocalName == "scatterChart") | |
| { | |
| s = new ExcelScatterChartSerie(this, ns, n, isPivot); | |
| } | |
| else if (chart.ChartNode.LocalName == "lineChart") | |
| { | |
| s = new ExcelLineChartSerie(this, ns, n, isPivot); | |
| } | |
| else if (chart.ChartNode.LocalName == "pieChart" || | |
| chart.ChartNode.LocalName == "ofPieChart" || | |
| chart.ChartNode.LocalName == "pie3DChart" || | |
| chart.ChartNode.LocalName == "doughnutChart") | |
| { | |
| s = new ExcelPieChartSerie(this, ns, n, isPivot); | |
| } | |
| else | |
| { | |
| s = new ExcelChartSerie(this, ns, n, isPivot); | |
| } | |
| _list.Add(s); | |
| } | |
| } | |
| #region IEnumerable Members | |
| public IEnumerator GetEnumerator() | |
| { | |
| return (_list.GetEnumerator()); | |
| } | |
| /// <summary> | |
| /// Returns the serie at the specified position. | |
| /// </summary> | |
| /// <param name="PositionID">The position of the series.</param> | |
| /// <returns></returns> | |
| public ExcelChartSerie this[int PositionID] | |
| { | |
| get | |
| { | |
| return (_list[PositionID]); | |
| } | |
| } | |
| public int Count | |
| { | |
| get | |
| { | |
| return _list.Count; | |
| } | |
| } | |
| /// <summary> | |
| /// Delete the chart at the specific position | |
| /// </summary> | |
| /// <param name="PositionID">Zero based</param> | |
| public void Delete(int PositionID) | |
| { | |
| ExcelChartSerie ser = _list[PositionID]; | |
| ser.TopNode.ParentNode.RemoveChild(ser.TopNode); | |
| _list.RemoveAt(PositionID); | |
| } | |
| #endregion | |
| /// <summary> | |
| /// A reference to the chart object | |
| /// </summary> | |
| public ExcelChart Chart | |
| { | |
| get | |
| { | |
| return _chart; | |
| } | |
| } | |
| #region "Add Series" | |
| /// <summary> | |
| /// Add a new serie to the chart. Do not apply to pivotcharts. | |
| /// </summary> | |
| /// <param name="Serie">The Y-Axis range</param> | |
| /// <param name="XSerie">The X-Axis range</param> | |
| /// <returns></returns> | |
| public virtual ExcelChartSerie Add(ExcelRangeBase Serie, ExcelRangeBase XSerie) | |
| { | |
| if (_chart.PivotTableSource != null) | |
| { | |
| throw (new InvalidOperationException("Can't add a serie to a pivotchart")); | |
| } | |
| return AddSeries(Serie.FullAddressAbsolute, XSerie.FullAddressAbsolute,""); | |
| } | |
| /// <summary> | |
| /// Add a new serie to the chart.Do not apply to pivotcharts. | |
| /// </summary> | |
| /// <param name="SerieAddress">The Y-Axis range</param> | |
| /// <param name="XSerieAddress">The X-Axis range</param> | |
| /// <returns></returns> | |
| public virtual ExcelChartSerie Add(string SerieAddress, string XSerieAddress) | |
| { | |
| if (_chart.PivotTableSource != null) | |
| { | |
| throw (new InvalidOperationException("Can't add a serie to a pivotchart")); | |
| } | |
| return AddSeries(SerieAddress, XSerieAddress, ""); | |
| } | |
| internal protected ExcelChartSerie AddSeries(string SeriesAddress, string XSeriesAddress, string bubbleSizeAddress) | |
| { | |
| XmlElement ser = _node.OwnerDocument.CreateElement("ser", ExcelPackage.schemaChart); | |
| XmlNodeList node = _node.SelectNodes("c:ser", _ns); | |
| if (node.Count > 0) | |
| { | |
| _node.InsertAfter(ser, node[node.Count-1]); | |
| } | |
| else | |
| { | |
| InserAfter(_node, "c:varyColors,c:grouping,c:barDir,c:scatterStyle", ser); | |
| } | |
| int idx = FindIndex(); | |
| ser.InnerXml = string.Format("<c:idx val=\"{1}\" /><c:order val=\"{1}\" /><c:tx><c:strRef><c:f></c:f><c:strCache><c:ptCount val=\"1\" /></c:strCache></c:strRef></c:tx>{5}{0}{2}{3}{4}", AddExplosion(Chart.ChartType), idx, AddScatterPoint(Chart.ChartType), AddAxisNodes(Chart.ChartType), AddSmooth(Chart.ChartType), AddMarker(Chart.ChartType)); | |
| ExcelChartSerie serie; | |
| switch (Chart.ChartType) | |
| { | |
| case eChartType.Bubble: | |
| case eChartType.Bubble3DEffect: | |
| serie = new ExcelBubbleChartSerie(this, NameSpaceManager, ser, _isPivot) | |
| { | |
| Bubble3D=Chart.ChartType==eChartType.Bubble3DEffect, | |
| Series = SeriesAddress, | |
| XSeries = XSeriesAddress, | |
| BubbleSize = bubbleSizeAddress | |
| }; | |
| break; | |
| case eChartType.XYScatter: | |
| case eChartType.XYScatterLines: | |
| case eChartType.XYScatterLinesNoMarkers: | |
| case eChartType.XYScatterSmooth: | |
| case eChartType.XYScatterSmoothNoMarkers: | |
| serie = new ExcelScatterChartSerie(this, NameSpaceManager, ser, _isPivot); | |
| break; | |
| case eChartType.Radar: | |
| case eChartType.RadarFilled: | |
| case eChartType.RadarMarkers: | |
| serie = new ExcelRadarChartSerie(this, NameSpaceManager, ser, _isPivot); | |
| break; | |
| case eChartType.Surface: | |
| case eChartType.SurfaceTopView: | |
| case eChartType.SurfaceTopViewWireframe: | |
| case eChartType.SurfaceWireframe: | |
| serie = new ExcelSurfaceChartSerie(this, NameSpaceManager, ser, _isPivot); | |
| break; | |
| case eChartType.Pie: | |
| case eChartType.Pie3D: | |
| case eChartType.PieExploded: | |
| case eChartType.PieExploded3D: | |
| case eChartType.PieOfPie: | |
| case eChartType.Doughnut: | |
| case eChartType.DoughnutExploded: | |
| case eChartType.BarOfPie: | |
| serie = new ExcelPieChartSerie(this, NameSpaceManager, ser, _isPivot); | |
| break; | |
| case eChartType.Line: | |
| case eChartType.LineMarkers: | |
| case eChartType.LineMarkersStacked: | |
| case eChartType.LineMarkersStacked100: | |
| case eChartType.LineStacked: | |
| case eChartType.LineStacked100: | |
| serie = new ExcelLineChartSerie(this, NameSpaceManager, ser, _isPivot); | |
| if (Chart.ChartType == eChartType.LineMarkers || | |
| Chart.ChartType == eChartType.LineMarkersStacked || | |
| Chart.ChartType == eChartType.LineMarkersStacked100) | |
| { | |
| ((ExcelLineChartSerie)serie).Marker = eMarkerStyle.Square; | |
| } | |
| ((ExcelLineChartSerie)serie).Smooth = ((ExcelLineChart)Chart).Smooth; | |
| break; | |
| case eChartType.BarClustered: | |
| case eChartType.BarStacked: | |
| case eChartType.BarStacked100: | |
| case eChartType.ColumnClustered: | |
| case eChartType.ColumnStacked: | |
| case eChartType.ColumnStacked100: | |
| case eChartType.BarClustered3D: | |
| case eChartType.BarStacked3D: | |
| case eChartType.BarStacked1003D: | |
| case eChartType.ColumnClustered3D: | |
| case eChartType.ColumnStacked3D: | |
| case eChartType.ColumnStacked1003D: | |
| case eChartType.ConeBarClustered: | |
| case eChartType.ConeBarStacked: | |
| case eChartType.ConeBarStacked100: | |
| case eChartType.ConeCol: | |
| case eChartType.ConeColClustered: | |
| case eChartType.ConeColStacked: | |
| case eChartType.ConeColStacked100: | |
| case eChartType.CylinderBarClustered: | |
| case eChartType.CylinderBarStacked: | |
| case eChartType.CylinderBarStacked100: | |
| case eChartType.CylinderCol: | |
| case eChartType.CylinderColClustered: | |
| case eChartType.CylinderColStacked: | |
| case eChartType.CylinderColStacked100: | |
| case eChartType.PyramidBarClustered: | |
| case eChartType.PyramidBarStacked: | |
| case eChartType.PyramidBarStacked100: | |
| case eChartType.PyramidCol: | |
| case eChartType.PyramidColClustered: | |
| case eChartType.PyramidColStacked: | |
| case eChartType.PyramidColStacked100: | |
| serie = new ExcelBarChartSerie(this, NameSpaceManager, ser, _isPivot); | |
| ((ExcelBarChartSerie)serie).InvertIfNegative=false; | |
| break; | |
| default: | |
| serie = new ExcelChartSerie(this, NameSpaceManager, ser, _isPivot); | |
| break; | |
| } | |
| serie.Series = SeriesAddress; | |
| serie.XSeries = XSeriesAddress; | |
| _list.Add(serie); | |
| return serie; | |
| } | |
| bool _isPivot; | |
| internal void AddPivotSerie(ExcelPivotTable pivotTableSource) | |
| { | |
| var r=pivotTableSource.WorkSheet.Cells[pivotTableSource.Address.Address]; | |
| _isPivot = true; | |
| AddSeries(r.Offset(0, 1, r._toRow - r._fromRow + 1, 1).FullAddressAbsolute, r.Offset(0, 0, r._toRow - r._fromRow + 1, 1).FullAddressAbsolute,""); | |
| } | |
| private int FindIndex() | |
| { | |
| int ret = 0, newID=0; | |
| if (_chart.PlotArea.ChartTypes.Count > 1) | |
| { | |
| foreach (var chart in _chart.PlotArea.ChartTypes) | |
| { | |
| if (newID>0) | |
| { | |
| foreach (ExcelChartSerie serie in chart.Series) | |
| { | |
| serie.SetID((++newID).ToString()); | |
| } | |
| } | |
| else | |
| { | |
| if (chart == _chart) | |
| { | |
| ret += _list.Count + 1; | |
| newID=ret; | |
| } | |
| else | |
| { | |
| ret += chart.Series.Count; | |
| } | |
| } | |
| } | |
| return ret-1; | |
| } | |
| else | |
| { | |
| return _list.Count; | |
| } | |
| } | |
| #endregion | |
| #region "Xml init Functions" | |
| private string AddMarker(eChartType chartType) | |
| { | |
| if (chartType == eChartType.Line || | |
| chartType == eChartType.LineStacked || | |
| chartType == eChartType.LineStacked100 || | |
| chartType == eChartType.XYScatterLines || | |
| chartType == eChartType.XYScatterSmooth || | |
| chartType == eChartType.XYScatterLinesNoMarkers || | |
| chartType == eChartType.XYScatterSmoothNoMarkers) | |
| { | |
| return "<c:marker><c:symbol val=\"none\" /></c:marker>"; | |
| } | |
| else | |
| { | |
| return ""; | |
| } | |
| } | |
| private string AddScatterPoint(eChartType chartType) | |
| { | |
| if (chartType == eChartType.XYScatter) | |
| { | |
| return "<c:spPr><a:ln w=\"28575\"><a:noFill /></a:ln></c:spPr>"; | |
| } | |
| else | |
| { | |
| return ""; | |
| } | |
| } | |
| private string AddAxisNodes(eChartType chartType) | |
| { | |
| if ( chartType == eChartType.XYScatter || | |
| chartType == eChartType.XYScatterLines || | |
| chartType == eChartType.XYScatterLinesNoMarkers || | |
| chartType == eChartType.XYScatterSmooth || | |
| chartType == eChartType.XYScatterSmoothNoMarkers || | |
| chartType == eChartType.Bubble || | |
| chartType == eChartType.Bubble3DEffect) | |
| { | |
| return "<c:xVal /><c:yVal />"; | |
| } | |
| else | |
| { | |
| return "<c:val />"; | |
| } | |
| } | |
| private string AddExplosion(eChartType chartType) | |
| { | |
| if (chartType == eChartType.PieExploded3D || | |
| chartType == eChartType.PieExploded || | |
| chartType == eChartType.DoughnutExploded) | |
| { | |
| return "<c:explosion val=\"25\" />"; //Default 25; | |
| } | |
| else | |
| { | |
| return ""; | |
| } | |
| } | |
| private string AddSmooth(eChartType chartType) | |
| { | |
| if (chartType == eChartType.XYScatterSmooth || | |
| chartType == eChartType.XYScatterSmoothNoMarkers) | |
| { | |
| return "<c:smooth val=\"1\" />"; //Default 25; | |
| } | |
| else | |
| { | |
| return ""; | |
| } | |
| } | |
| #endregion | |
| } | |
| } |