| /******************************************************************************* | 
 |  * 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 | 
 |     } | 
 | } |