blob: 674bb736953dd1cb2d8ab6bf63734527abe51cfd [file] [log] [blame]
/*******************************************************************************
* 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 30-AUG-2010
* Jan Källman License changed GPL-->LGPL 2011-12-16
*******************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Xml;
using OfficeOpenXml.Packaging;
using OfficeOpenXml.Utils;
namespace OfficeOpenXml.Table;
/// <summary>
/// Table style Enum
/// </summary>
public enum TableStyles {
None,
Custom,
Light1,
Light2,
Light3,
Light4,
Light5,
Light6,
Light7,
Light8,
Light9,
Light10,
Light11,
Light12,
Light13,
Light14,
Light15,
Light16,
Light17,
Light18,
Light19,
Light20,
Light21,
Medium1,
Medium2,
Medium3,
Medium4,
Medium5,
Medium6,
Medium7,
Medium8,
Medium9,
Medium10,
Medium11,
Medium12,
Medium13,
Medium14,
Medium15,
Medium16,
Medium17,
Medium18,
Medium19,
Medium20,
Medium21,
Medium22,
Medium23,
Medium24,
Medium25,
Medium26,
Medium27,
Medium28,
Dark1,
Dark2,
Dark3,
Dark4,
Dark5,
Dark6,
Dark7,
Dark8,
Dark9,
Dark10,
Dark11,
}
/// <summary>
/// An Excel Table
/// </summary>
public class ExcelTable : XmlHelper, IEqualityComparer<ExcelTable> {
protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
"autoFilter",
"tableColumns",
"tableStyleInfo",
];
internal ExcelTable(ZipPackageRelationship rel, ExcelWorksheet sheet)
: base(sheet.NameSpaceManager) {
WorkSheet = sheet;
TableUri = UriHelper.ResolvePartUri(rel.SourceUri, rel.TargetUri);
RelationshipID = rel.Id;
TableXml = sheet._package.GetXmlDocument(TableUri);
TopNode = TableXml.DocumentElement;
Address = new(GetXmlNodeString("@ref"));
}
/// <summary>
/// Provides access to the XML data representing the table in the package.
/// </summary>
internal XmlDocument TableXml { get; }
/// <summary>
/// The package internal URI to the Table Xml Document.
/// </summary>
private Uri TableUri { get; }
internal string RelationshipID { get; set; }
private const string _idPath = "@id";
internal int Id => GetXmlNodeInt(_idPath);
private const string _namePath = "@name";
private const string _displayNamePath = "@displayName";
/// <summary>
/// The name of the table object in Excel
/// </summary>
public string Name => GetXmlNodeString(_namePath);
/// <summary>
/// The worksheet of the table
/// </summary>
public ExcelWorksheet WorkSheet { get; }
private ExcelAddressBase _address;
/// <summary>
/// The address of the table
/// </summary>
public ExcelAddressBase Address {
get => _address;
set {
_address = value;
SetXmlNodeString("@ref", value.Address);
WriteAutoFilter(ShowTotal);
}
}
internal ExcelTableColumnCollection _cols;
/// <summary>
/// Collection of the columns in the table
/// </summary>
public ExcelTableColumnCollection Columns {
get {
if (_cols == null) {
_cols = new(this);
}
return _cols;
}
}
private const string _headerrowcountPath = "@headerRowCount";
private const string _autofilterPath = "d:autoFilter/@ref";
/// <summary>
/// If the header row is visible or not
/// </summary>
public bool ShowHeader {
get => GetXmlNodeInt(_headerrowcountPath) != 0;
set {
if (Address._toRow - Address._fromRow < 0 && value
|| Address._toRow - Address._fromRow == 1 && value && ShowTotal) {
throw (new("Cant set ShowHeader-property. Table has too few rows"));
}
if (value) {
DeleteNode(_headerrowcountPath);
WriteAutoFilter(ShowTotal);
//for (int i = 0; i < Columns.Count; i++)
//{
// var v = WorkSheet.GetValue<string>(Address._fromRow, Address._fromCol + i);
// if (!string.IsNullOrEmpty(v) || v != _cols[i].Name)
// {
// _cols[i].Name = v;
// }
//}
} else {
SetXmlNodeString(_headerrowcountPath, "0");
DeleteAllNode(_autofilterPath);
}
}
}
internal ExcelAddressBase AutoFilterAddress {
get {
string a = GetXmlNodeString(_autofilterPath);
if (a == "") {
return null;
}
return new(a);
}
}
private void WriteAutoFilter(bool showTotal) {
string autofilterAddress;
if (ShowHeader) {
if (showTotal) {
autofilterAddress = ExcelCellBase.GetAddress(
Address._fromRow,
Address._fromCol,
Address._toRow - 1,
Address._toCol);
} else {
autofilterAddress = Address.Address;
}
SetXmlNodeString(_autofilterPath, autofilterAddress);
}
}
/// <summary>
/// If the header row has an autofilter
/// </summary>
public bool ShowFilter => ShowHeader && AutoFilterAddress != null;
private const string _totalsrowcountPath = "@totalsRowCount";
/// <summary>
/// If the total row is visible or not
/// </summary>
public bool ShowTotal {
get => GetXmlNodeInt(_totalsrowcountPath) == 1;
set {
if (value != ShowTotal) {
if (value) {
Address = new ExcelAddress(
WorkSheet.Name,
ExcelCellBase.GetAddress(
Address.Start.Row,
Address.Start.Column,
Address.End.Row + 1,
Address.End.Column));
} else {
Address = new ExcelAddress(
WorkSheet.Name,
ExcelCellBase.GetAddress(
Address.Start.Row,
Address.Start.Column,
Address.End.Row - 1,
Address.End.Column));
}
SetXmlNodeString("@ref", Address.Address);
if (value) {
SetXmlNodeString(_totalsrowcountPath, "1");
} else {
DeleteNode(_totalsrowcountPath);
}
WriteAutoFilter(value);
}
}
}
private const string _stylenamePath = "d:tableStyleInfo/@name";
/// <summary>
/// The style name for custum styles
/// </summary>
public string StyleName => GetXmlNodeString(_stylenamePath);
private const string _showfirstcolumnPath = "d:tableStyleInfo/@showFirstColumn";
/// <summary>
/// Display special formatting for the first row
/// </summary>
public bool ShowFirstColumn => GetXmlNodeBool(_showfirstcolumnPath);
private const string _showlastcolumnPath = "d:tableStyleInfo/@showLastColumn";
/// <summary>
/// Display special formatting for the last row
/// </summary>
public bool ShowLastColumn => GetXmlNodeBool(_showlastcolumnPath);
private const string _showrowstripesPath = "d:tableStyleInfo/@showRowStripes";
/// <summary>
/// Display banded rows
/// </summary>
public bool ShowRowStripes => GetXmlNodeBool(_showrowstripesPath);
private const string _showcolumnstripesPath = "d:tableStyleInfo/@showColumnStripes";
/// <summary>
/// Display banded columns
/// </summary>
public bool ShowColumnStripes => GetXmlNodeBool(_showcolumnstripesPath);
private const string _totalsrowcellstylePath = "@totalsRowCellStyle";
/// <summary>
/// Named style used for the total row
/// </summary>
public string TotalsRowCellStyle => GetXmlNodeString(_totalsrowcellstylePath);
private const string _datacellstylePath = "@dataCellStyle";
/// <summary>
/// Named style used for the data cells
/// </summary>
public string DataCellStyleName => GetXmlNodeString(_datacellstylePath);
private const string _headerrowcellstylePath = "@headerRowCellStyle";
/// <summary>
/// Named style used for the header row
/// </summary>
public string HeaderRowCellStyle => GetXmlNodeString(_headerrowcellstylePath);
public bool Equals(ExcelTable x, ExcelTable y) {
return x.WorkSheet == y.WorkSheet && x.Id == y.Id && x.TableXml.OuterXml == y.TableXml.OuterXml;
}
public int GetHashCode(ExcelTable obj) {
return obj.TableXml.OuterXml.GetHashCode();
}
}