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