/******************************************************************************* * 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 21-MAR-2011 * Jan Källman License changed GPL-->LGPL 2011-12-16 *******************************************************************************/ using System; using System.Collections.Generic; using System.Text; using System.Xml; namespace OfficeOpenXml.Table.PivotTable { /// /// Base collection class for pivottable fields /// /// public class ExcelPivotTableFieldCollectionBase : IEnumerable { protected ExcelPivotTable _table; internal List _list = new List(); internal ExcelPivotTableFieldCollectionBase(ExcelPivotTable table) { _table = table; } public IEnumerator GetEnumerator() { return _list.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return _list.GetEnumerator(); } public int Count { get { return _list.Count; } } internal void AddInternal(T field) { _list.Add(field); } internal void Clear() { _list.Clear(); } public T this[int Index] { get { if (Index < 0 || Index >= _list.Count) { throw (new ArgumentOutOfRangeException("Index out of range")); } return _list[Index]; } } } public class ExcelPivotTableFieldCollection : ExcelPivotTableFieldCollectionBase { internal ExcelPivotTableFieldCollection(ExcelPivotTable table, string topNode) : base(table) { } /// /// Indexer by name /// /// /// public ExcelPivotTableField this[string name] { get { foreach (var field in _list) { if (field.Name.Equals(name,StringComparison.InvariantCultureIgnoreCase)) { return field; } } return null; } } /// /// Returns the date group field. /// /// The type of grouping /// The matching field. If none is found null is returned public ExcelPivotTableField GetDateGroupField(eDateGroupBy GroupBy) { foreach (var fld in _list) { if (fld.Grouping is ExcelPivotTableFieldDateGroup && (((ExcelPivotTableFieldDateGroup)fld.Grouping).GroupBy) == GroupBy) { return fld; } } return null; } /// /// Returns the numeric group field. /// /// The matching field. If none is found null is returned public ExcelPivotTableField GetNumericGroupField() { foreach (var fld in _list) { if (fld.Grouping is ExcelPivotTableFieldNumericGroup) { return fld; } } return null; } } /// /// Collection class for Row and column fields in a Pivottable /// public class ExcelPivotTableRowColumnFieldCollection : ExcelPivotTableFieldCollectionBase { internal string _topNode; internal ExcelPivotTableRowColumnFieldCollection(ExcelPivotTable table, string topNode) : base(table) { _topNode=topNode; } /// /// Add a new row/column field /// /// The field /// The new field public ExcelPivotTableField Add(ExcelPivotTableField Field) { SetFlag(Field, true); _list.Add(Field); return Field; } /// /// Insert a new row/column field /// /// The field /// The position to insert the field /// The new field internal ExcelPivotTableField Insert(ExcelPivotTableField Field, int Index) { SetFlag(Field, true); _list.Insert(Index, Field); return Field; } private void SetFlag(ExcelPivotTableField field, bool value) { switch (_topNode) { case "rowFields": if (field.IsColumnField || field.IsPageField) { throw(new Exception("This field is a column or page field. Can't add it to the RowFields collection")); } field.IsRowField = value; field.Axis = ePivotFieldAxis.Row; break; case "colFields": if (field.IsRowField || field.IsPageField) { throw (new Exception("This field is a row or page field. Can't add it to the ColumnFields collection")); } field.IsColumnField = value; field.Axis = ePivotFieldAxis.Column; break; case "pageFields": if (field.IsColumnField || field.IsRowField) { throw (new Exception("Field is a column or row field. Can't add it to the PageFields collection")); } if (_table.Address._fromRow < 3) { throw(new Exception(string.Format("A pivot table with page fields must be located above row 3. Currenct location is {0}", _table.Address.Address))); } field.IsPageField = value; field.Axis = ePivotFieldAxis.Page; break; case "dataFields": break; } } /// /// Remove a field /// /// public void Remove(ExcelPivotTableField Field) { if(!_list.Contains(Field)) { throw new ArgumentException("Field not in collection"); } SetFlag(Field, false); _list.Remove(Field); } /// /// Remove a field at a specific position /// /// public void RemoveAt(int Index) { if (Index > -1 && Index < _list.Count) { throw(new IndexOutOfRangeException()); } SetFlag(_list[Index], false); _list.RemoveAt(Index); } } /// /// Collection class for data fields in a Pivottable /// public class ExcelPivotTableDataFieldCollection : ExcelPivotTableFieldCollectionBase { internal ExcelPivotTableDataFieldCollection(ExcelPivotTable table) : base(table) { } /// /// Add a new datafield /// /// The field /// The new datafield public ExcelPivotTableDataField Add(ExcelPivotTableField field) { var dataFieldsNode = field.TopNode.SelectSingleNode("../../d:dataFields", field.NameSpaceManager); if (dataFieldsNode == null) { _table.CreateNode("d:dataFields"); dataFieldsNode = field.TopNode.SelectSingleNode("../../d:dataFields", field.NameSpaceManager); } XmlElement node = _table.PivotTableXml.CreateElement("dataField", ExcelPackage.schemaMain); node.SetAttribute("fld", field.Index.ToString()); dataFieldsNode.AppendChild(node); //XmlElement node = field.AppendField(dataFieldsNode, field.Index, "dataField", "fld"); field.SetXmlNodeBool("@dataField", true,false); var dataField = new ExcelPivotTableDataField(field.NameSpaceManager, node, field); ValidateDupName(dataField); _list.Add(dataField); return dataField; } private void ValidateDupName(ExcelPivotTableDataField dataField) { if(ExistsDfName(dataField.Field.Name, null)) { var index = 2; string name; do { name = dataField.Field.Name + "_" + index++.ToString(); } while (ExistsDfName(name,null)); dataField.Name = name; } } internal bool ExistsDfName(string name, ExcelPivotTableDataField datafield) { foreach (var df in _list) { if (((!string.IsNullOrEmpty(df.Name) && df.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) || (string.IsNullOrEmpty(df.Name) && df.Field.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)))) && datafield != df) { return true; } } return false; } /// /// Remove a datafield /// /// public void Remove(ExcelPivotTableDataField dataField) { XmlElement node = dataField.Field.TopNode.SelectSingleNode(string.Format("../../d:dataFields/d:dataField[@fld={0}]", dataField.Index), dataField.NameSpaceManager) as XmlElement; if (node != null) { node.ParentNode.RemoveChild(node); } _list.Remove(dataField); } } }